禁用 RTTI 的动态广播

发布于 2024-12-08 22:26:32 字数 510 浏览 1 评论 0原文

我很想知道在禁用 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-rttion 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

拧巴小姐 2024-12-15 22:26:32

阅读标准,在 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

Virtual functions support dynamic binding and objectoriented
programming. A class that declares or inherits a virtual function is
called a polymorphic class.

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.

滥情空心 2024-12-15 22:26:32

在 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.

清醇 2024-12-15 22:26:32

找出答案的最简单方法就是尝试一下。

您会发现,某些动态转换将被标记为非法。有些不会。例如,当您使用动态转换向上转换为明确的基类时,转换在编译时就已知。

附录
回复“因为(至少在 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.

流心雨 2024-12-15 22:26:32

试一下:

#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

Just try it:

#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;
}

Without -fno-rtti, the program compiles and the output is:

failed to cast

With -fno-rtti, the program failed to compile:

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

You can also test this online here: https://onlinegdb.com/pYTQu2ne2

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文