Dynamic_cast兼容性?

时间:2017-06-08 20:18:10

标签: c++

我正在阅读有关dynamic_cast的信息,然后我遇到了以下声明(from cplusplus.com):

  

兼容性说明:此类型的dynamic_cast需要运行时类型   用于跟踪动态类型的信息(RTTI)。一些编译器   支持此功能作为默认禁用的选项。这个   需要使用dynamic_cast来启用运行时类型检查   适当地使用这些类型。

示例后:

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

作者的意思是&#34;这种类型的dynamic_cast&#34;?是不是dynamic_cast只用于多态类(差不多)?并且他提到这个RTTI是动态转换工作所需要的东西,这是否意味着你必须谨慎使用dynamic_cast,因为你不知道它是否被编译器完全支持,因此比其他的转换风险更大那些不需要这个RTTI的运营商?

3 个答案:

答案 0 :(得分:3)

兼容性说明涉及前一段(和代码示例):

  

但是dynamic_cast也可以向下转换(从指针到基础转换为指向派生的)多态类(具有虚拟成员的类),如果 - 并且只有 - 指向object是目标类型的有效完整对象。

这是真的:向下转换需要一个多态类型的对象,RTTI在运行时遍历对象的继承树。

其他类型的dynamic_cast之前的段落中解释

  

这自然包括指针upcast (从指针到派生转换为指针到base),与隐式转换允许的方式相同。 / p>

此处不需要RTTI,因为对象的基础始终是静态已知的。

因此,您只需要完整阅读周围的文字,以便了解您正在阅读的文字的背景。

但是,我会注意到,根据我的经验,默认情况下禁用RTTI的编译器基本上是闻所未闻的。我并不是说不存在 - 可能有一些针对嵌入式平台的针对特定行业的特定编译器,这样做可以将程序员在Makefile中保存几个字节。但是大多数人使用的编译器(GCC,Clang,Visual Studio,ICC,Comeau)都是我所知道的,将RTTI作为标准打包并保留,直到你要求关闭它为止。

答案 1 :(得分:0)

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

您可以使用上面提到的编译器选项-fno-rtti使编译器禁止生成有关具有虚函数的每个类的此类信息,但很少推荐。

“其他”案例涉及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);后执行相同操作,编译器将为此特定行提供以下错误消息:错误:-fno-rtti 不允许使用'dynamic_cast'。请注意,即使使用void*(已手动或默认设置),投射到-fno-rtti仍然有效。

答案 2 :(得分:-1)

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

因此,我解释

  

因为您不知道编译器是否完全支持它

as

  

因为您的代码可能已使用rtti禁用编译。