禁用 RTTI 的动态广播
我很想知道在禁用 RTTI 的情况下使用动态转换编译代码时会发生什么 (在 GCC 上使用 -fno-rtti
或在 Visual Studio 上使用 /GR-
)。编译器是否“回退”到 static_cast
?由于(至少在 VS 上)它只发出警告,编译后的代码会做什么?
更具体地说,如果我在没有 RTTI 的情况下编译一段代码,并且我确信使用dynamic_cast 不会出现错误(即 dynamic_cast
可以安全地替换为 static_cast< /code>) 就像这个:
class A{ /*...*/ } ;
class B : public A {
int foo() { return 42 ;}
} ;
//...
A * myA = new B() ;
int bar = (dynamic_cast<B*>(myA))->foo() ;
I'm curious to know what happens when compiling code with a dynamic cast whith RTTI disabled
(either with -fno-rtti
on GCC or with /GR-
on visual studio). Does the compiler "falls back" to static_cast
? Since (at least on VS) it does only issue a warning, what will the compiled code do ?
More specifically, what bad things could happen if I compile without RTTI a code where I'm sure that there are no error possible with dynamic_cast (i.e. where dynamic_cast
could be safely replaced by a static_cast
) like this one :
class A{ /*...*/ } ;
class B : public A {
int foo() { return 42 ;}
} ;
//...
A * myA = new B() ;
int bar = (dynamic_cast<B*>(myA))->foo() ;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
阅读标准,在 5.2.7/6 中我们发现除非目标是源的明确基础,否则源必须是多态类型。然后在10.3/1
换句话说,该标准似乎没有说明您的问题。在这种情况下,标准不允许编译器关闭 RTTI,因此对于每个编译器,您需要检查其文档以了解会发生什么。根据这篇阅读,我认为这是一个编译器问题,而不是标签所示的 C++ 语言问题。
或者,当您知道足够时,只需使用
static_cast
即可完全避免该问题。Reading the standard, in 5.2.7/6 we find that unless the target is an unambiguous base of the source, source must be a polymorphic type. Then in 10.3/1
In other words the standard doesn't seem to say anything about your question. In this case, the standard doesn't allow for a compiler to turn off RTTI so for each compiler you need to check its documentation to see what would happen. Based on this reading, I think this is a compiler question, not a C++ language question as the tag indicates.
Alternately you can avoid the problem completely by just using
static_cast
when you know it's sufficient.在 MSVC 中,如果您的代码未在启用 RTTI 的情况下编译,并且在没有运行时检查的情况下无法执行转换,则会引发 __non_rtti_object 异常。
In MSVC, if your code is not compiled with RTTI enabled, a
__non_rtti_object
exception will be thrown, if the cast cannot be performed without a run-time check.找出答案的最简单方法就是尝试一下。
您会发现,某些动态转换将被标记为非法。有些不会。例如,当您使用动态转换向上转换为明确的基类时,转换在编译时就已知。
附录
回复“因为(至少在 VS 上)它只发出警告 ...”
忽略警告将带来危险。最好的办法是确保您的代码编译时不会出现警告,并且警告级别设置得非常高(并且可能会转换为错误)。其次,最好是查看您收到的每一个警告,确保不会发生任何意外。在这种情况下,就会发生一些不愉快的事情。你真的不应该关心这个不幸的事件是如何实施的。你应该关心的是摆脱它。
The easiest way to find out is to try it.
What you will find is that some of your dynamic casts will be flagged as illegal. Some won't. For example, the conversion is known at compile time when you use dynamic cast to upcast to an unambiguous base class.
Addendum
Re "Since (at least on VS) it does only issue a warning ..."
Ignore warnings at your peril. The best thing to do is to ensure that your code compiles without warnings, with warning levels set very high (and possibly converted to errors). Second best is to look at each and every warning you get and ensure that nothing untoward happens. In this case, something untoward will happen. You really should not care how that untoward event is implemented. What you should care about is getting rid of it.
试一下:
没有
-fno-rtti
,程序编译,输出为:使用
-fno-rtti
,程序编译失败:您也可以在线测试一下此处:https://onlinegdb.com/pYTQu2ne2
Just try it:
Without
-fno-rtti
, the program compiles and the output is:With
-fno-rtti
, the program failed to compile:You can also test this online here: https://onlinegdb.com/pYTQu2ne2