1

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-stylecast 来实现:

B* b = (B*)a;

所以,我的问题是在哪些情况/情况下完全有必要使用此运算符,即没有其他选择?

4

5 回答 5

4

但是,同样可以通过使用 C 风格的转换来实现:

不,它不能 :)

根据定义,C-Style cast 将尝试执行一系列const_cast,static_castreinterpret_cast1来实现您想要的演员而不是 dynamic_cast. 因此,本质上,这里的 C 风格转换等效于 astatic_cast如果实际动态类型不匹配,则将具有未定义的行为(相反,在这种情况下,动态转换将nullptr在指针的情况下返回并std::bad_cast在引用的情况下抛出)。

也就是说,如果您确定要转换为正确的类型,请使用static_cast(或 C-style cast,但我个人不喜欢它)。但是,如果您不确定,请使用dynamic_cast

1 C-Style cast 也可用于转换为私有基类,这不能用前面提到的一系列 C++-Style casts 完成

于 2013-07-11T15:54:18.837 回答
2

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

于 2013-07-11T15:51:04.607 回答
2

如果您的问题是什么时候应该使用dynamic_cast 而不是 C-style cast,那么答案总是(也就是说,如果您必须在 C-style cast 和 dynamic_cast 之间进行选择,总是更喜欢 dynamic_cast)。

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

如果您的问题是何时应该在不需要它的设计上使用 dynamic_cast,答案几乎是永远不会。通常,您应该避免要求您的实现向下转换指针或引用的设计。当您的实现迫使您向下转换时,这通常是设计不佳的标志(即正确的解决方案可能是重构,而不是向下转换)。

于 2013-07-11T15:51:49.043 回答
1

添加到上面的一些答案中,即使您忽略了这个事实是聪明的,在 c++ 代码中dynamic_cast使用 c 样式转换来代替static// cast确实很危险constreinterpret

根据转换时可见的内容[例如,如果头文件被删除,这可能会发生变化],c 风格的转换可能无法正确执行指针运算,并最终导致您得到一个垃圾指针。

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

于 2013-07-11T16:14:05.437 回答
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 风格的转换将在此处返回不正确的指针。

于 2013-07-11T16:49:59.333 回答