Pointer denotes the virtual function table of Base class--4 bytes
Pointer denotes the virtual function Func2() which only belongs to class Derived--4 bytes (as far as I'm concerned, derived class which has no non-virtual base classes and gets its unique virtual functions should has its own virtual table)
Ah, I see the problem now. That's not quite how virtual function tables work. When Base
is defined, the compiler notices it requires a virtual table, and generates a virtual table for Base
, with one pointer (Func
), which points to the Base::Func
implementation. When Derived
is defined, the compiler notices it inherits from Base
, and generates a function table for Base
that has two pointers, Func
points to Derived::Func
, and Func2
points to Derived::Func2
.
Then, if an instance of Base
is created, it's function table pointer that you mention points at the Base
table, and any calls to Func
will be redirected to Base::Func
.
If an instance of Derived
is created, it's internal Base
object's virtual function table pointer will point at the Derived
table instead. Base
only knows how to access the Func
pointer, but that Func
pointer points at Derived::Func
now, and so that's what get's called. It doesn't realize it's pointing at a different table. In code, it might look more like this:
using voidFunctionType = void(*)();
struct BaseVTable {
voidFunctionType Func;
}BaseVTableGlobal;
struct Base {
Base() :vTable(&BaseVTableGlobal) {}
void Func() {vTable->Func();}
BaseVTable* vTable; //4 bytes
int BaseValue; //4 bytes
}; //total is 8 bytes
struct DerivedVTable : public BaseVTable {
voidFunctionType Func;
voidFunctionType Func2;
}DerivedVTableGlobal;
//inherits 8 bytes, +4 for virtual inheritance = 12
struct Derived : virtual public Base {
Derived() :Base() {vTable = &DerivedVTableGlobal;} //the shared vTable points at DerivedVTableGlobal
void Func() {vTable->Func();} //base knows about Func, so this is easy
void Func2() {((DerivedVTable*)vTable)->Func2();} //base doesn't know about Func2
int DerivedValue; //4 bytes
}; //16 bytes total
So XCode is right. Derived
is "hijacking" Base
s virtual function table, and in fact, that's exactly how virtual functions do their magic.
(Assumptions everywhere, none of this is well-defined, virtual inheretence complicates things, etc etc etc)