如何停止在 C++ 中调用不兼容的方法?

Posted

技术标签:

【中文标题】如何停止在 C++ 中调用不兼容的方法?【英文标题】:How to stop calling incompatible method in C++? 【发布时间】:2019-12-20 08:58:42 【问题描述】:

我在处理我的个人项目时遇到了这个问题。 简而言之,我有 2 个多态类:basederived 以及一个函数 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”类型的参数不兼容

如何调用 super() 使其在 2 和 3 中兼容?

FreeMYbatisTool本地插件不兼容怎么办

线程(c++ 中的并行计算)是不是与优化级别(gcc)不兼容?

代理和 ARC,不兼容?

暗黑破坏神2为啥停止工作已经兼容性设过,已经测试过