C ++中dynamic_cast运算符的强制必要性

时间:2013-07-11 15:45:15

标签: c++ casting dynamic-cast

dynamic_cast通常在我们有基类指针并希望将其向下转换为派生类时使用。例如,

class A
{
      public:
      virtual void foo();
};

class B : public A 
{
      public:
      void foo();
};

main()
{
    A* a = new B();
    B* b = dynamic_cast<B*> (a);
}

但是,使用C-style强制转换:

也可以实现同样的目标
B* b = (B*)a;

所以,我的问题是,在完全有必要使用这个算子的情况/情况下,即没有其他选择?

5 个答案:

答案 0 :(得分:4)

  

但是,同样也可以通过使用C风格的演员来实现:

不,它不能:)

根据定义,C-Style演员将尝试执行一系列const_caststatic_castreinterpret_cast 1 来实现您想要的演员表但是 dynamic_cast。所以,基本上,这里C风格的强制转换相当于static_cast,如果实际的动态类型不匹配,它将具有未定义的行为(相反,在这种情况下,动态强制转换将返回nullptr以防万一指针并在引用的情况下抛出std::bad_cast

也就是说,如果你某些你正在投射到正确的类型,那么使用static_cast(或C风格的演员,但我个人不这样做喜欢它)。但如果您不确定,请使用dynamic_cast

1 C-Style强制转换也可用于强制转换为私有基础,这不能通过前面提到的C ++系列进行 - 样式转换

答案 1 :(得分:2)

当您实际上不知道a指向B dynamic_cast类型的对象时,将返回一个空指针,您可以检查并相应地处理该情况。使用C风格的转换,您会得到一个指针,但是当您尝试使用它时,会发生未定义的行为。

答案 2 :(得分:2)

如果你的问题是你应该使用 dynamic_cast而不是C风格的演员,答案总是如此(也就是说,如果你必须在C风格的演员表和dynamic_cast之间做出选择,总是更喜欢dynamic_cast)

总的来说,尽量不要在C ++中使用C风格的强制转换。它们很难通过工具定位(除非该工具是编译器),并且它们导致必须在重构时显式读取代码以查找转换(错误的来源)。

如果你的问题是你应该使用 dynamic_cast而不是那些不需要它的设计,那么答案几乎从不。通常,您应该避免需要实现向下指针或引用的设计。当你的实现迫使你进行向下投射时,通常是设计不佳的标志(即正确的解决方案可能是重构,而不是向下投射)。

答案 3 :(得分:1)

添加上面的一些答案,即使你忽略事实dynamic_cast很聪明,在c ++代码中使用c样式转换来代替static / const / {{ 1}}施放非常危险

取决于强制转换时可见的内容[例如,如果删除头文件可能会更改],c样式强制转换可能无法正确执行指针算法并使您最终得到垃圾指针。

您永远不会想要添加或删除头文件来更改代码的含义。 C ++强制转换没有这个问题,如果编译器无法解决它应该做什么,你将会遇到编译失败,而不是随着c样式转换你可能得到的随机运行时崩溃。

答案 4 :(得分:0)

dynamic_cast返回不同(和正确)结果的一种情况是从非最左边的基类进行转换时:

class A { 
public:
   int x; 
}

class B {
public:
   virtual void foo();
};

class C : public A, public B
{
     public:
     void foo();
};

main()
{
   B* b = new C();
   C* c = dynamic_cast<C*>(b);
}

C风格的强制转换会在这里返回错误的指针。