禁用RTTI的dynamic_cast

时间:2011-10-07 12:11:37

标签: c++ rtti dynamic-cast

我很想知道在使用RTTI禁用的动态转换编译代码时会发生什么 (在GCC上使用-fno-rtti或在Visual Studio上使用/GR-)。编译器是否“退回”static_cast?因为(至少在VS上)它只发出一个警告,编译的代码会做什么?

更具体地说,如果我在没有RTTI的情况下编译代码,我确信在dynamic_cast中没有错误可能会发生什么不好的事情(即dynamic_cast可以安全地替换为static_cast )喜欢这个:

class A{ /*...*/ } ;
class B : public A {
    int foo() { return 42 ;}
} ;
//...
A * myA = new B() ;
int bar = (dynamic_cast<B*>(myA))->foo() ;

4 个答案:

答案 0 :(得分:11)

阅读标准,在5.2.7 / 6中我们发现除非目标是源的明确基础,否则源必须是多态类型。然后在10.3 / 1

  

虚拟功能支持动态绑定和面向对象   节目。声明或继承虚函数的类是   称为多态类。

换句话说,标准似乎没有说明你的问题。在这种情况下,标准不允许编译器关闭RTTI,因此对于每个编译器,您需要检查其文档以查看将发生的情况。根据这个读数,我认为这是一个编译器问题,而不是标签所指示的C ++语言问题。

或者,当您知道它已足够时,只需使用static_cast即可完全避免此问题。

答案 1 :(得分:8)

在MSVC中,如果未使用RTTI编译代码,如果在没有运行时检查的情况下无法执行强制转换,则会抛出__non_rtti_object异常。

答案 2 :(得分:6)

最简单的方法是尝试一下。

你会发现你动态演员的部分会被标记为非法。有些人不会。例如,当您使用动态强制转换为明确的基类时,转换在编译时是已知的。

<强>附录
重新“从(至少在VS上)它只发出警告 ...” 忽视警告你的危险。最好的办法是确保您的代码在没有警告的情况下编译,警告级别设置得非常高(并且可能转换为错误)。第二个最好的方法是查看你得到的每一个警告,并确保不会发生任何不幸事件。在这种情况下,会发生一些不幸的事情。你真的不应该关心这个不幸的事件是如何实现的。你应该关心的是摆脱它。

答案 3 :(得分:0)

试试吧:

#include <iostream>
#include <typeinfo>
#include <typeindex>
#include <memory>
#include <vector>
#include <array>
#include <string>

class Base {
public:
  virtual ~Base() {
  }
};

class A: public Base {
};

class B: public Base {
};

using namespace std;

int main() {
  A *a = new A;
  auto *ptr = dynamic_cast<B*>(a);

  if (!ptr)
    std::cout << "failed to cast" << std::endl;

  return 0;
}

没有-fno-rtti,程序编译并输出:

failed to cast

使用 -fno-rtti,程序无法编译:

main.cpp:25:35: error: ‘dynamic_cast’ not permitted with -fno-rtti
     auto* ptr = dynamic_cast<B*>(a);
                                   ^

您也可以在这里在线测试:https://onlinegdb.com/pYTQu2ne2