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