在钻石等级中向下
Downcast in a diamond hierarchy
为什么static_cast
不能从虚拟基地向下投射?
struct A {};
struct B : public virtual A {};
struct C : public virtual A {};
struct D : public B, public C {};
int main()
{
D d;
A& a = d;
D* p = static_cast<D*>(&a); //error
}
G++ 4.5 说:
error: cannot convert from base ‘A’ to derived type ‘D’ via virtual base ‘A’
解决方案是使用dynamic_cast
? 但为什么。什么是理性?
--编辑--
下面很好的答案。不过,没有答案详细说明子对象和 vtables 最终是如何排序的。以下文章给出了一些关于 gcc 的好例子:
http://www.phpcompiler.org/articles/virtualinheritance.html#Downcasting
显而易见的答案是:因为标准是这么说的。 这标准中这背后的动机是static_cast
应该接近微不足道——最多是一个简单的加法或将常量减去指针。 落魄在哪里到虚拟基地将需要更复杂的代码:也许即使在某处的 vtable 中有一个额外的条目。 (它需要的不仅仅是常量,因为位置 D
相对于A
如果有进一步的推导,可能会发生变化。转换显然是可行的,因为当您调用时一个A*
上的虚函数,并且该函数被实现在D
中,编译器必须这样做,但额外的开销是被认为不适合static_cast
. (据推测,在这种情况下使用static_cast
的唯一原因是优化,因为dynamic_cast
通常是首选溶液。 因此,当static_cast
可能与 dynamic_cast
无论如何,为什么要支持它。
因为如果对象实际上是 E
类型(派生自 D),则A
子对象相对于D
子对象的位置可能与对象实际D
的位置不同。
如果您考虑从 A 转换为 C,它实际上已经发生了。当您分配 C 时,它必须包含 A 的实例,并且它位于某个特定的偏移量。但是当你分配 D 时,C 子对象引用了 B 附带的 A 实例,因此它的偏移量是不同的。
- 什么是钻石问题?是一系列问题还是特定问题?
- 钻石继承虚拟成员铸造与指针
- 接口的钻石继承(C++)
- 在钻石问题的求解中,为什么要虚拟地继承两次grand-parent类
- C++如何解决钻石问题?
- c++ 中的函数重载如何在没有钻石继承的情况下工作?
- 多个虚拟(钻石)继承
- C++解决没有虚拟继承的钻石继承问题
- 多种继承C 的钻石问题
- 如何调用所有基本类的复制构造函数,以在C 中复制钻石继承中最派生的类对象
- 假设钻石继承打破了C++的封装是否正确?
- C++多个钻石继承和纯虚函数
- 如何解决钻石问题的这种歧义
- 解决QT类的特定C 钻石问题
- 在C++中尝试基于用户确定的宽度打印钻石
- 虚拟继承如何解决 c++ 中的多重继承(钻石)?它将走哪条路
- 首选钻石继承中一个类的变量
- 钻石继承,C++ 处理
- 复杂的钻石问题:C++虚拟继承
- 将 Boost.Serialization 直接与虚拟钻石继承一起工作