目前我正在学习动态转换,因此我正在测试各种代码片段。
我测试了下面的代码,有或没有(2)中标记的虚拟析构函数,发现第(3)行只有正确,如果有第(2)行。没有它,代码不会编译。但为什么?有趣的是,似乎根本不需要第(1)行。
struct A {
virtual ~A() = default; \\ (1)
};
struct B {
virtual ~B() = default; \\ (2)
};
struct D : A, B {};
B* pb = new D();
A* pa = dynamic_cast<A*>(pb); \\ (3)
dynamic_cast
需要确定运行时的行为。根据铸造对象的实际类型,它将返回nullptr
或目标类型的有效指针。
为了在运行时发生这种情况,C ++实现需要访问一些额外的information about the type at run-time。管理此信息需要执行一些额外的操作。开销很小但存在。
不总是需要动态铸造。如果不需要,C ++语言设计者决定不创建不必要的开销。因此,除非您说需要多态,否则编译器将尝试在编译时尽可能多地解决所有类型问题。
说多态和动态类型的方法是在类中至少有一个虚拟成员函数。
如果您在程序中非常清楚源对象的类型与目标对象类型兼容,则可以使用static_cast
,如here所述。
但这不适用于你的情况,因为pb
是一个*B
(静态类型),因为一般来说*B
不能被铸造到*A
,因为这两种类型完全不相关。
但是考虑到它的多重继承,*D
(动态类型)可以被铸造到*A
。这就是为什么需要dynamic_cast
的原因:跟踪pb指向的对象的原始D类型。并且这要求类至少具有如上所述的虚函数。