我有三堂课:
class A {};
class B : virtual public A {};
class C : virtual public A {};
class D: public B, public C {};
尝试从A *到B *的静态转换时出现以下错误:
cannot convert from base A to derived type B via virtual base A
为了了解转换系统,您需要深入研究对象模型。
简单分层模型的经典表示是包含:如果B
源自A
,则B
对象实际上将在其自己的属性旁边包含一个A
子对象。
对于这种模型,向下转换是通过编译时已知的偏移量进行的简单指针操作,该偏移量取决于B
的内存布局。
这是static_cast的作用:将静态类型转换称为静态类型,因为对于类型转换所需的计算是在编译时完成的,无论是指针算术还是转换(*)。
但是,当virtual
继承开始时,事情就会变得更加困难。主要问题是,在继承virtual
的情况下,所有子类都共享该子对象的相同实例。为此,B
将具有指向A
的指针,而不是A
适当的指针,并且A
基类对象将在B
之外实例化。
因此,在编译时无法推断出必要的指针算法:这取决于对象的运行时类型。
[只要有运行时类型依赖项,就需要RTTI(运行时类型信息),并且使用RTTI进行强制转换是dynamic_cast
的工作。摘要:
static_cast
dynamic_cast
[另外两个也是编译时强制转换,但是它们是如此具体,以至于很容易记住它们的用途...而且它们很臭,因此最好不要使用它们。
(*)正如@curiousguy在评论中指出的那样,这仅适用于向下转换。 static_cast
允许上载,而不考虑虚拟继承或简单继承,尽管这样也不必进行强制转换。
据我所知,您需要使用dynamic_cast
,因为继承是virtual
,您正在向下转换。
在这种情况下,您不能使用static_cast
,因为编译器在编译时不知道B相对于A的偏移量。必须在运行时根据最派生对象的确切类型来计算偏移量。因此,您必须使用dynamic_cast
。
是,您必须使用dynamic_cast,但是必须使基类A具有多态性,例如通过添加虚拟dtor。
根据标准文档,
$ 5.2.9 / 2-“表达式e可以是使用显式转换为类型T形式的static_caststatic_cast(e)如果声明对于某些人来说,“ T t(e);”的格式正确发明了临时变量t(8.5)。“
我不知道这是否“安全”,但是。