Dynamic_cast兼容性?

Dynamic_cast compatibility?

我正在阅读有关 dynamic_cast 的内容,然后我遇到了以下语句 (from cplusplus.com):

Compatibility note: This type of dynamic_cast requires Run-Time Type Information (RTTI) to keep track of dynamic types. Some compilers support this feature as an option which is disabled by default. This needs to be enabled for runtime type checking using dynamic_cast to work properly with these types.

例子后:

// dynamic_cast
#include <iostream>
#include <exception>
using namespace std;

class Base { virtual void dummy() {} };
class Derived: public Base { int a; };

int main () {
  try {
    Base * pba = new Derived;
    Base * pbb = new Base;
    Derived * pd;

    pd = dynamic_cast<Derived*>(pba);
    if (pd==0) cout << "Null pointer on first type-cast.\n";

    pd = dynamic_cast<Derived*>(pbb);
    if (pd==0) cout << "Null pointer on second type-cast.\n";

  } catch (exception& e) {cout << "Exception: " << e.what();}
  return 0;
}

作者"this type of dynamic_cast"是什么意思? dynamic_cast不就是用来做多态的类(差不多)吗?他提到这个 RTTI 是动态转换工作所必需的,这是否意味着您必须谨慎使用 dynamic_cast 因为您不知道编译器是否完全支持它,因此会增加风险比其他不需要此 RTTI 的铸造操作员?

您提到的部分中的作者提到了使用 dynamic_cast 和多态类型时的情况:更准确地说,当您编写类似 dynamic_cast<X*>(p) 的内容时。 在这种情况下,您将需要 运行-时间类型信息,以便 dynamic_cast 完全可以使用(参见下面的示例)。

您可以使用提到的编译器选项 -fno-rtti 让编译器禁止生成关于每个 class 虚函数的此类信息,但很少推荐这样做。

"Other" 个案例是关于 dynamic_castvoid* 中的使用。

例如,考虑以下代码:

class A {
public:
  virtual ~A() = default;
};

class B : public A {};

int main()
{
  A *p = new B();
  void *pv = dynamic_cast<void*>(p);
  //B *pb = dynamic_cast<B*>(p);

  delete p;

  return 0;
}

如果您使用 g++ test.cpp -std=c++11 -fno-rtti 编译代码,那就没问题了。但是,如果您在取消注释 B *pb = dynamic_cast<B*>(p); 后执行相同的操作,编译器将针对该特定行给出以下错误消息:error: 'dynamic_cast' not permitted with -fno- rtti.请注意,即使使用 -fno-rtti(已手动或默认设置),转换为 void* 也有效。

rtti 在运行时很昂贵,一些嵌入式系统使用标志编译,禁用它。它给你的只是 dynamic_casttypeid.

因此,我解读

because you do not know if it is supported fully by the compiler

作为

because your code could have been compiled with rtti disabled.

兼容性说明与前一段(和代码示例)相关:

But dynamic_cast can also downcast (convert from pointer-to-base to pointer-to-derived) polymorphic classes (those with virtual members) if -and only if- the pointed object is a valid complete object of the target type.

确实如此:向下转型需要一个多态类型的对象,RTTI 需要在运行时遍历对象的继承树。

另一种dynamic_cast之前的段落中有解释:

This naturally includes pointer upcast (converting from pointer-to-derived to pointer-to-base), in the same way as allowed as an implicit conversion.

这里不需要 RTTI 作为对象的基础is/are 总是静态已知的。

所以你只需要完整地阅读周围的文字,就能理解你正在阅读的单词的上下文。

但是,我要指出,根据我的经验,默认情况下禁用 RTTI 的编译器基本上是闻所未闻的。我并不是说 none 存在——可能有一些针对嵌入式平台的特定行业的小众编译器这样做是为了在程序员的 Makefile 中节省几个字节。但是据我所知,大多数人使用的编译器(GCC、Clang、Visual Studio、ICC、Comeau)都将 RTTI 作为标准打包并保持打开状态,直到您要求将其关闭。