This is going to be extremely platform-dependant, but I think we can understand what's going on.
First off, the Standard doesn't specify how virtual inheitence is to be implemented. As far as the Standard is concerned, there's not even any such thing as a vtable.
ABCDerived
has BBase
and CBase
Each of which is comprised of an int
. There is also a single instance of ABase
which is comprised of an int
. Finally there is a vtable ptr.
The size of an int
is platform dependant -- it's not necesarrily 4 bytes. But if we assume it is 4 bytes, and the size of the vtable is also 4 bytes, we have:
int [ABCDerived] = 4 bytes
int [CBase] = 4 bytes
int [BBase] = 4 bytes
int [ABase] = 4 bytes
vtable = 4 bytes
-------------
20 bytes
That doesn't mean the sizeof (ABCDerived)
is 20 however. Alignment comes in to play here as well. The Standard allows compilers to increase the size of an object so that the size is divisible by a number of whole words.
Consider:
class ABase{
int iMem;
};
class BBase : public virtual ABase {
int iMem;
};
class CBase : public virtual ABase {
int iMem;
};
class ABCDerived : public BBase, public CBase {
int iMem;
};
int main()
{
ABCDerived d;
BBase& b = d;
ABase* ab = &b;
CBase& c = d;
ABase* ac = &b;
cout << hex << (void*) ab << "\n"
<< hex << (void*) ac << "\n";
cout << sizeof (d) << "\n" << sizeof (int) << "\n";
}
The output is 28
on my 64 bit Linux machine.
However if I turn on packing (using a platform-dependant #pragma switch):
#pragma pack (1)
The output is now 20.
So, the long and the short of all this is:
There is a ton of platform-dependant stuff going on here. You can't say the size of the object is this or that, at least without employing more platform-dependant stuff and knowing how your compiler actually implements virtual inheritence. The size of it is whatever the size of it is.