如何停止在 C++ 中调用不兼容的方法?
Posted
技术标签:
【中文标题】如何停止在 C++ 中调用不兼容的方法?【英文标题】:How to stop calling incompatible method in C++? 【发布时间】:2019-12-20 08:58:42 【问题描述】:我在处理我的个人项目时遇到了这个问题。
简而言之,我有 2 个多态类:base
和 derived
以及一个函数 caller()
,它试图调用 derived
中存在但不在 base
中的方法。 derived
类还有一个在该方法内部使用的基础中不存在的变量。
如果使用base *
类型的参数调用caller()
,它将失败并返回Segmentation fault
,因为它找不到base
类的方法中使用的变量,如下例所示:
#include <iostream>
class base
virtual void someFunction() /* Do something */
;
class derived : public base
public:
void someFunction() override /* Do something else */
void functionNotInBase() // Do something base can't
std::cout << variableNotInBase << std::endl;
;
private:
int variableNotInBase 5;
;
void caller(base *p)
dynamic_cast<derived *>(p)->functionNotInBase();
int main()
auto d = new derived();
auto b = new base();
caller(d); // Ok, pointer to derived
caller(static_cast<base *>(d)); // Ok, pointer to derived (cast to base)
caller(b); // Error, classes are not compatible (no variable in base to be printed)
delete b;
delete d;
我现在的问题是:如何阻止caller()
调用不兼容类型的方法(不是从derived
继承的所有内容)?在这种情况下,caller()
可能什么都不做,但它不应该因Segmentation fault
而失败。
另一个问题是我正在为 Arduino 开发,它没有带有 typeid()
函数的类型支持库,可以在运行时检查指针类型。
谢谢。
【问题讨论】:
您是否尝试过您接受的答案?只是好奇。如果没有 rtti 支持,dynamic_cast 也不应该工作,而且它对 Arduino 上的很多人都不起作用。所以我想知道它对你有什么作用。 @n.'pronouns'm。一般来说,这更像是一个关于dynamic_cast
的问题,但是是的,该解决方案在 Arduino 上不起作用,因此在我的特殊情况下,虚拟基类函数似乎是唯一的方法。
【参考方案1】:
你必须检查dynamic_cast
的结果,你目前可以(并且做)尊重nullptr
:
void caller(base *p)
auto der = dynamic_cast<derived *>(p);
if (der) der->functionNotInBase();
【讨论】:
请不要这样做。动态演员不是为了这个。【参考方案2】:动态演员表是一种创可贴。永远不要在面向对象代码的业务逻辑中使用动态转换。如果你认为你需要它,那么你就有了设计问题,它会在路上给你带来麻烦。
你有这个逻辑:
if object is derived
call derived method
else
do nothing
这个逻辑应该移到基类的虚函数中。
class base
virtual void do_businesst()
;
class derived : public base
void do_business() override
functionNotInBase();
;
【讨论】:
以上是关于如何停止在 C++ 中调用不兼容的方法?的主要内容,如果未能解决你的问题,请参考以下文章
“void(*)(int wall)”类型的 C++ 参数与“int”类型的参数不兼容