Reputation:
So it's impossible to downcast using static_cast
with virtual inheritance, but how is it possible to do the following upcast:
class Base {...};
class Derived : public virtual Base {...};
...
Derived *d = new Derived();
Base *b = static_cast<Base*>(d);
Memory layout of the object:
[ derived part | base part ]
I know that upcasting is considered "safe", but how can the compiler know the offset to the base sub-object at compile-time, when the inheritance is virtual? Does the static_cast
use the vtable
?
This is especially confusing when we have something like this (note that it's not virtual):
class Third : public Derived {...};
...
Derived *d = new Third(); // non-virtual upcast, no offset will be added
Base *b = static_cast<Base*>(d);
This time I used the same static_cast
line, but the offset to the Base
sub-object is different!
Memory layout of the object:
[ derived part | third part | base part ]
So how can it be determined at compile time, if it depends on the actual dynamic type of the object d
points to?
Upvotes: 10
Views: 3247
Reputation: 153955
When you have a pointer to a Derived
in your case, it is clear which Base
is to be used and you can even implicitly convert the pointer to Derived
to a pointer to Base
! If any address adjustment is needed the compiler will figure out how to do so using embedded pointer, a vtable, or whatever: the exact approach isn't prescribed by the C++ standard. What is done exact depends on the ABI. For example, for the Itanium C++ ABI it seems the offsets for virtual bases are store in the virtual tables.
Upvotes: 4