I am baffled by the VIRTUAL keyword. I am trying to find how does compiler implement this in memory. ok so let me explain with examples. I am using Microsoft Visual studio 2010 as implementation of virtual depends on compiler.
here is the first code
#include<iostream>
class one
{
    int _a;
public:
    virtual ~one(){}
};
class two:public one
{
    int _a;
public:
    virtual ~two(){}
};
int main()
{
    using namespace std;
    cout<<"sizeof two="<<sizeof(two)<<endl;
    return 0;
}
o/p is 12 bytes, because of _vptr_two,one::_a and two::_a
here is another example code
#include<iostream>
class one
{
    int _a;
public:
    virtual ~one(){}
};
class two
{
    int _a;
public:
    virtual ~two(){}
};
class three:virtual public one,virtual public two
{
};
int main()
{
    using namespace std;
    cout<<"sizeof three="<<sizeof(three)<<endl;
    return 0;
}
in this case o/p is 20 bytes :O, how come?? Please explain!! According to me it should be 16 bytes. __vptr_three(pointer to vtable), _vptr1_three(pointer to virtual base class table), one::_a and two::_a. And why virtual base class table is maintained ?
This pdf contains everything that you need to understand about, how virtual inheritance is implemented in VC++, by the writer of the compiler.
Below is the disassembly for the constructor of class three,
00A516BD  cmp         dword ptr [ebp+8],0 
00A516C1  je          three::three+60h (0A516F0h) 
00A516C3  mov         eax,dword ptr [this] 
00A516C6  mov         dword ptr [eax],offset three::`vbtable' (0A57828h) => 4 Bytes
00A516CC  mov         ecx,dword ptr [this] 
00A516CF  add         ecx,8 
00A516D2  call        one::one (0A51253h) 
00A516D7  or          dword ptr [ebp-0D4h],1 
00A516DE  mov         ecx,dword ptr [this] 
00A516E1  add         ecx,10h 
00A516E4  call        two::two (0A512BCh) 
00A516E9  or          dword ptr [ebp-0D4h],2 
00A516F0  mov         eax,dword ptr [this] 
00A516F3  mov         ecx,dword ptr [eax] 
00A516F5  mov         edx,dword ptr [ecx+4] 
00A516F8  mov         eax,dword ptr [this] 
00A516FB  mov         dword ptr [eax+edx],offset three::`vftable' (0A57820h)  => 4 Bytes
00A51702  mov         eax,dword ptr [this] 
00A51705  mov         ecx,dword ptr [eax] 
00A51707  mov         edx,dword ptr [ecx+8] 
00A5170A  mov         eax,dword ptr [this] 
00A5170D  mov         dword ptr [eax+edx],offset three::`vftable' (0A57814h)   => 4 Bytes
00A51714  mov         eax,dword ptr [this] 
00A51717  pop         edi  
00A51718  pop         esi  
00A51719  pop         ebx  
00A5171A  add         esp,0D8h 
As you can see above, 
The virtual base table pointer takes 4 bytes, (vbtable)
2 virtual function table pointer takes 4 * 2 = 8 bytes, (vftable)
The member one::_a takes 4 bytes
The member two::_a takes 4 bytes
Hence in all 20 bytes. The reason for 2 virtual function table pointers is given in the pdf (page 17) as follows,
"In Visual C++, to avoid costly conversions to the virtual base P when fetching a vftable entry, new virtual functions of T, receive entries in a new vftable, requiring a new vfptr, introduced at the top of T."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With