Why static_cast
cannot downcast from a virtual base ?
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 says:
error: cannot convert from base ‘A’ to derived type ‘D’ via virtual base ‘A’
The solution is to use dynamic_cast
? but why. What is the rational ?
-- edit --
Very good answers below. No answers detail exactly how sub objects and vtables end up to be ordered though. The following article gives some good examples for gcc:
http://www.phpcompiler.org/articles/virtualinheritance.html#Downcasting
The obvious answer is: because the standard says so. The motivation behind this in the standard is that
static_cast
should be close to trivial—at most, a simple addition or subtraction of a constant to the pointer. Where s the downcast to a virtual base would require more complicated code: perhaps even with an additional entry in the vtable somewhere. (It requires something more than constants, since the position ofD
relative toA
may change if there is further derivation.) The conversion is obviously doable, since when you call a virtual function on anA*
, and the function is implemented inD
, the compiler must do it, but the additional overhead was considered inappropriate forstatic_cast
. (Presumably, the only reason for usingstatic_cast
in such cases is optimization, sincedynamic_cast
is normally the preferred solution. So whenstatic_cast
is likely to be as expensive asdynamic_cast
anyway, why support it.)Because if the object was actually of type
E
(derived from D), the location ofA
subobject relative toD
subobject could be different than if the object is actuallyD
.It actually already happens if you consider instead casting from A to C. When you allocate C, it has to contain instance of A and it lives at some specific offset. But when you allocate D, the C subobject refers to the instance of A that came with B, so it's offset is different.