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;
所以,我的问题是,在完全有必要使用这个算子的情况/情况下,即没有其他选择?
答案 0 :(得分:4)
但是,同样也可以通过使用C风格的演员来实现:
不,它不能:)
根据定义,C-Style演员将尝试执行一系列const_cast
,static_cast
和reinterpret_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风格的强制转换会在这里返回错误的指针。