动态转型(dynamic_cast)何时应该用于静态转型(static_cast)之上?

4
我想知道在什么情况下必须或应该使用dynamic_cast而不是static_cast,同时需要提供示例。我已经阅读了this SO question,但它并没有提供任何具体的示例。我假设大多数示例将涉及多态类类型。目前我知道使用dynamic_cast而不是static_cast的唯一原因是我不确定我正在使用的具体类型。
其他想法:
- 侧向转换(在多重继承中) - 在虚拟继承层次结构中向上转换到基类 - 当在使用多重继承的类中向“最右边”的继承类型进行转换时,指针是否会更改(如果使用static_cast)?
“如果类型未知”是唯一的原因吗?如果不是,能否提供示例,以证明为什么必须或应该使用dynamic_cast而不是static_cast?

1
据我所知,dynamic_cast 仅用于从基类向派生类的转换,并且基类必须至少有一个虚函数。在几乎所有其他情况下,您都应该使用 static_cast - Mooing Duck
2个回答

2
一般情况下,无论如何,当在类层次结构中进行转换时,都应该使用dynamic_cast。唯一的一个可能例外是从派生类转换到基类(当然是指指针或引用)。否则,在类层次结构中使用static_cast 的唯一时间是当分析工具提示您必须使用时。 static_cast 更常用于转换为或从void*,或确保空指针常量的正确类型,或进行不涉及指针或引用的转换(例如static_cast<double>( someInt ))。

"static_cast在转换为或从void*时使用更频繁,尽管dynamic_cast<void*>有其自己的含义。因此,决定使用哪种转换方式并不是由于你要转换为void*,而是取决于你想要的结果是什么。" - Steve Jessop
1
static_cast如何验证从void*到其他类型的转换的有效性?void*没有静态类型信息(除了它是一个指针)。 - void.pointer
@RobertDailey:它不验证有效性,除了略高于语法级别的规则之外,即所有void*和任何指向对象类型的指针之间的转换都是有效的。而static_cast<void*>dynamic_cast<void*>之间的区别在于,当应用于多态层次结构中的基类指针时,前者返回与传入相同的地址,而后者返回您具有基类指针的最派生对象的地址。它很少有用,但就是这样... - Steve Jessop
“it” 是指 static_cast,没错我就是这么说的。static_cast 的一个目的是可以反转任何隐式转换。从 MyClass* 到 void* 存在一种隐式转换,而通过 static_cast 可以从 void* 转回到 MyClass*。 - Steve Jessop
@SteveJessop 我指的是从 void 进行转换,就像这样:static_cast<MyClass*>( myVoidPointerVariable )。你说的是“to/from”,据我所知这样不会编译(必须使用 reinterpret_cast)。我有误解吗?(抱歉我上次评论的措辞不正确,已经删除了) - void.pointer
显示剩余3条评论

0

有一种情况下,即使您知道动态类型,也必须使用dynamic_cast,那就是从虚基类向更派生的类型进行转换:

struct A { };
struct B : virtual A { };
struct C : virtual A { };
struct D : B, C { };

A * p = new D;
D * q = dynamic_cast<D*>(p);

当然,原因是虚拟基类只在运行时确定。
另一个使用 dynamic_cast 的方法是通过 强制转换为 void* 来发现最派生对象的地址,尽管这并不完全清楚是否是必要的语言特性。(我成功 设计了一个用例,但它大多是学术性的。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接