为什么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
?但为什么。什么是理性?
- 编辑 -
下面非常好的答案。没有答案详细说明子对象和vtable最终如何订购。以下文章给出了gcc的一些很好的例子:
http://www.phpcompiler.org/articles/virtualinheritance.html#Downcasting
答案 0 :(得分:11)
显而易见的答案是:因为标准是这样说的。该
标准背后的动机是static_cast
应该接近琐碎 - 最多,一个简单的添加或
将常量减去指针。垂头丧气的地方
到虚拟基础需要更复杂的代码:也许
即使在vtable的某个地方有额外的条目。 (它
需要的东西不仅仅是常数,因为它的位置
如果有进一步的推导,相对于D
的{{1}}可能会发生变化。)
当你打电话时,转换显然是可行的
A
上的虚函数,该函数已实现
在A*
中,编译器必须这样做,但额外的开销是
被认为不适合D
。 (据推测,
在这种情况下使用static_cast
的唯一原因是
优化,因为static_cast
通常是首选
解。因此dynamic_cast
可能会像static_cast
一样昂贵
dynamic_cast
无论如何,为什么支持它。)
答案 1 :(得分:10)
因为如果对象实际上是E
类型(从D派生),A
子对象相对于D
子对象的位置可能与对象实际为{{ 1}}。
如果您考虑从A转换为C,实际上已经发生了。当您分配C时,它必须包含A的实例并且它存在于某个特定的偏移处。但是当你分配D时,C子对象引用了B附带的A实例,所以它的偏移是不同的。