我很想知道在使用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() ;
答案 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