2013-08-25 13 views
1

我的代碼是:什麼是虛擬基類子對象之前?

class A { /* ... */ }; 
class B : virtual public A { /* ... */ }; 
class C : virtual public A { /* ... */ }; 

class X { /* ... */ }; 
class Y : virtual public X { /* ... */ }; 
class Z : virtual public X { /* ... */ }; 

class D : public B, public C, public Y, public Z { 
public: 
    __declspec(noinline) D() { printf("ctor in D\n"); } 
    __declspec(noinline) virtual ~D() { printf("dtor in D\n"); } 
}; 

int main() 
{ 
    D *pd = new D; 
    delete pd; 
    return 0; 
} 

我發現有虛基類子對象前4米字節的空間。我不明白他們做了什麼。

delete pd; 
00161D01 mov   eax,dword ptr [edi+4] 
00161D04 lea   ecx,[edi+4] 
00161D07 mov   eax,dword ptr [eax+4] 
00161D0A add   ecx,eax 
00161D0C push  1 
00161D0E mov   eax,dword ptr [ecx] 
00161D10 call  dword ptr [eax+8] 
00161D13 pop   edi 

; call in delete goes here 
00161D20 sub   ecx,dword ptr [ecx-4]      ; <-- 
00161D23 jmp   D::`scalar deleting destructor' (0161C40h) 


__declspec(noinline) D() { printf("ctor in D, %d\n", &val_); } 
00161A80 push  ebp 
00161A81 mov   ebp,esp 
00161A83 sub   esp,8 
00161A86 push  ebx 
00161A87 push  esi 
00161A88 mov   esi,ecx 
00161A8A push  edi 
00161A8B lea   ecx,[esi+28h] 
00161A8E mov   dword ptr [ebp-8],0 
00161A95 mov   dword ptr [esi+4],163424h 
00161A9C mov   dword ptr [esi+0Ch],1633F8h 
00161AA3 mov   dword ptr [esi+14h],1633F8h 
00161AAA mov   dword ptr [esi+1Ch],163438h 
00161AB1 call  A::A (01616B0h) 
00161AB6 lea   ecx,[esi+30h] 
00161AB9 call  X::X (01618A0h) 
00161ABE push  ecx 
00161ABF mov   ecx,esi 
00161AC1 call  B::B (0161740h) 
00161AC6 push  ecx 
00161AC7 lea   ecx,[esi+8] 
00161ACA call  C::C (01617F0h) 
00161ACF push  ecx 
00161AD0 lea   ecx,[esi+10h] 
00161AD3 call  Y::Y (0161920h) 
00161AD8 push  ecx 
00161AD9 lea   ecx,[esi+18h] 
00161ADC call  Z::Z (01619D0h) 
00161AE1 mov   edx,esi 
00161AE3 mov   dword ptr [esi+8],163394h 
00161AEA mov   eax,dword ptr [edx+4] 
00161AED mov   dword ptr [edx],1633F0h 
00161AF3 mov   dword ptr [esi+10h],16338Ch 
00161AFA mov   dword ptr [esi+18h],163414h 
00161B01 mov   eax,dword ptr [eax+4] 
00161B04 mov   dword ptr [eax+edx+4],163404h 
00161B0C mov   eax,dword ptr [edx+4] 
00161B0F mov   eax,dword ptr [eax+8] 
00161B12 mov   dword ptr [eax+edx+4],1633E4h 
00161B1A mov   eax,dword ptr [edx+4] 
00161B1D mov   ecx,dword ptr [eax+4] 
00161B20 lea   eax,[ecx-24h] 
00161B23 mov   dword ptr [ecx+edx],eax      ; <-- 
00161B26 mov   eax,dword ptr [edx+4] 
00161B29 mov   ecx,dword ptr [eax+8] 
00161B2C lea   eax,[ecx-2Ch] 
00161B2F mov   dword ptr [ecx+edx],eax      ; <-- 
00161B32 lea   eax,[edx+20h] 
00161B35 push  eax 
00161B36 push  163318h 
00161B3B call  dword ptr ds:[16303Ch] 
; ... 


    __declspec(noinline) virtual ~D() { printf("dtor in D\n"); } 
00161BB0 push  ebx 
00161BB1 push  esi 
00161BB2 push  edi 
00161BB3 mov   edi,ecx 
00161BB5 push  163370h 
00161BBA mov   eax,dword ptr [edi-24h] 
00161BBD mov   dword ptr [edi-28h],1633F0h 
00161BC4 mov   dword ptr [edi-20h],163394h 
00161BCB mov   dword ptr [edi-18h],16338Ch 
00161BD2 mov   dword ptr [edi-10h],163414h 
00161BD9 mov   eax,dword ptr [eax+4] 
00161BDC mov   dword ptr [eax+edi-24h],163404h 
00161BE4 mov   eax,dword ptr [edi-24h] 
00161BE7 mov   eax,dword ptr [eax+8] 
00161BEA mov   dword ptr [eax+edi-24h],1633E4h 
00161BF2 mov   eax,dword ptr [edi-24h] 
00161BF5 mov   ecx,dword ptr [eax+4] 
00161BF8 lea   eax,[ecx-24h] 
00161BFB mov   dword ptr [ecx+edi-28h],eax     ; <-- 
00161BFF mov   eax,dword ptr [edi-24h] 
00161C02 mov   edx,dword ptr [eax+8] 
00161C05 lea   eax,[edx-2Ch] 
00161C08 mov   dword ptr [edx+edi-28h],eax     ; <-- 
00161C0C call  dword ptr ds:[16303Ch] 
00161C12 add   esp,4 
00161C15 lea   ecx,[edi-8] 
00161C18 call  Z::~Z (0161A20h) 
; ... 

在構造函數和析構函數中,值都是0.最小化的值恰好是虛擬基類子對象的偏移量。

VS2012,發佈模式。

+0

大概是'D'本身的vptr? –

+0

我不這麼認爲,到'D'的vptr被設置爲'00161AED mov dword ptr [edx],1633F0h'並且vptr不能是0 – QingYun

+1

(另外:[強制性閱讀](http://www.phpcompiler。 org/articles/virtualinheritance.html)。) –

回答