Consider this code:
class X { public: int i; };
class A : public virtual X { public: int j; };
class B : public virtual X { public: double d; };
class C : public A, public B { public: int k; };
// cannot resolve location of pa->X::i at compile-time
void foo( const A* pa ) { pa->i = 1024; }
main() {
foo( new A );
foo( new C );
// ...
}
In the book "Inside C++ object model", it is said that:
the compiler cannot fix the physical offset of
X::i
accessed throughpa
withinfoo()
, since the actual type ofpa
can vary with each offoo()'s
invocations.
So, the compiler has to create something like this:
// possible compiler transformation
void foo( const A* pa ) { pa->__vbcX->i = 1024; }
If the program has a pointer to the virtual base class, how can't it resolve the memory address of that member at compile time? As far as I know, when each derived class object is created, the memory layout of each object consists of:
- all members in the base class
- a virtual pointer (of a virtual destructor)
- a pointer to the virtual base class of the derived object
- all of the members of the derived class object.
So, finding the base class member should simply be finding the right offset from the starting address of the derived class object. But why can't it be resolved?