Question

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?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top