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 );
// ...
}
It is said that the compiler cannot fix the physical offset of X::i accessed through pa within foo(), since the actual type of pa can vary with each of foo()'s invocations in the book "*Inside C++ object mode*l".
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.
For example, suppose I have an object
C c_object
and A a_object
This is what I think about object c_object layout (suppose c_object start at address 1000:
1000: int i; //(subobject X)
1004: int j; //(subobject A)
1008: double d; //(subobject B)
1012: __vbcX; // which is at address 1000
1016: __vbcA; // which is at address 1004
1020: __vbcB; // which is at address 1008
1024: int k;
This is what I thought from what I read anyway, please verify and correct it for me.
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?