2013-01-05 69 views
1
class RootBase{ 
public: 
    RootBase():ai(12){} 
    virtual void fas(){ 
     printf("%p \n", this); 
    } 
private: 
    int ai; 

}; 

class Base : virtual public RootBase{ 

public: 
    Base():bai(1){} 

    virtual void fas(){ 

    } 
    virtual void fa(){ 

    } 
private: 
    int bai; 
}; 

Base *pBase = new Base; 

我測試了關於類的內存位置的虛擬繼承關係案例。結果讓我感到驚訝,因爲Base的大小是24 Bytes。我可以理解包含虛函數表指針,虛擬基表指針和成員變量的20個字節。爲什麼VS編譯器在對象內存中插入NULL

由PBASE指出基本對象的內存分配是:

60 77 41 00 68 77 41 00 01 00 00 00 00 00 00 00 54 77 41 00 0c 00 00 00 

但我不明白的13個含義 - 16字節,00000000,空(整數0的x86 32位)。四個字節0​​做什麼? (操作系統:贏得XP,IDE:視覺工作室8.0)

我也認爲整數0代表對齊填充,但沒有理由填充到8個字節。

+2

我可能沒有仔細看,但填充? – chris

+0

Mummmmmmm〜但是需要對齊嗎?我認爲這個類是四字節對齊。不需要填充。 –

+0

http://msdn.microsoft.com/en-us/library/453x4xdd.aspx –

回答

3

這是直接從您描述的類的對象佈局轉儲中獲取的。我希望它能回答你的問題。從多一點的研究中,我發現vtordispBase。是從虛擬基類聲明的類的構造函數或析構函數中調用虛函數時使用的偏移量。顯然它的通知他們你的虛函數表是。

Jonathan Caves, MSFT,比5年前:

它被用來很少 - 但我們必須把它添加到從虛基類繼承的類並重寫虛函數,以防萬一用戶不通話構造函數或析構函數中的虛函數。

注意:對於所有行上的1>序言,感到抱歉。責備微軟,它的工具。

1> class RootBase size(8): 
1>  +--- 
1> 0 | {vfptr} 
1> 4 | ai 
1>  +--- 
1> 
1> RootBase::[email protected]: 
1>  | &RootBase_meta 
1>  | 0 
1> 0 | &RootBase::fas 
1> 
1> RootBase::fas this adjustor: 0 
1> 
1> 
1> class Base size(24): 
1>  +--- 
1> 0 | {vfptr} 
1> 4 | {vbptr} 
1> 8 | bai 
1>  +--- 
1> 12 | (vtordisp for vbase RootBase) 
1>  +--- (virtual base RootBase) 
1> 16 | {vfptr} 
1> 20 | ai 
1>  +--- 
1> 
1> Base::[email protected]@: 
1>  | &Base_meta 
1>  | 0 
1> 0 | &Base::fa 
1> 
1> Base::[email protected]: 
1> 0 | -4 
1> 1 | 12 (Based(Base+4)RootBase) 
1> 
1> Base::[email protected]@: 
1>  | -16 
1> 0 | &(vtordisp) Base::fas 
1> 
1> Base::fas this adjustor: 16 
1> Base::fa this adjustor: 0 
1> 
1> vbi class  offset o.vbptr o.vbte fVtorDisp 
1>   RootBase  16  4  4   1 

服用確切相同的代碼,但使RootBase一個定期基類(即不virtual public RootBase,只是public RootBase)對物體佈局的顯著效果:

1> class RootBase size(8): 
1>  +--- 
1> 0 | {vfptr} 
1> 4 | ai 
1>  +--- 
1> 
1> RootBase::[email protected]: 
1>  | &RootBase_meta 
1>  | 0 
1> 0 | &RootBase::fas 
1> 
1> RootBase::fas this adjustor: 0 
1> 
1> 
1> class Base size(12): 
1>  +--- 
1>  | +--- (base class RootBase) 
1> 0 | | {vfptr} 
1> 4 | | ai 
1>  | +--- 
1> 8 | bai 
1>  +--- 
1> 
1> Base::[email protected]: 
1>  | &Base_meta 
1>  | 0 
1> 0 | &Base::fas 
1> 1 | &Base::fa 
1> 
1> Base::fas this adjustor: 0 
1> Base::fa this adjustor: 0 

注在虛擬基地消失的情況下,不再存儲「我是我」的偏移量,這似乎很好地清理了對象格式。

+0

非常感謝你!這就是問題所在!Vtordisp告訴程序,由於派生類是不完整的,我們只能找到虛擬表Vtordisp的基類,'0'表示現在被調用的指針只是基類虛表的地址,沒有偏移量。我的描述是正確的嗎? –

+0

@whoscraig:你的代碼片段顯示vfptr兩次(第一個代碼塊:0-4和16-20)。根據我的理解,類層次結構的vfptr只聲明一次。因此,因爲RootBase已經有了一個虛擬表格指針,它將由Base共享。因此,我仍然無法從您的答覆中瞭解Base如何可以爲24個字節,對於Base Base來說,總的字節爲:8個字節用於RootBase + 4個字節用於bai + 4個字節用於虛擬基址指針+ 4個字節用於vtordisp。這仍然留下4個字節。這些額外的4字節如何可以證明,如果不是填充? – stamhaney

+0

@stamhaney這段代碼(實際上這篇文章中的所有佈局層次結構)並不是由我生成的;它創建了我的ms的編譯器。從我所看到的一個vfptr屬於Base,另一個屬於RootBase。還要注意,如果沒有虛擬基類的繼承,實際上只有一個。我向你保證,我從我的輸出窗口複製該層次結構到這篇文章沒有任何錯誤。 – WhozCraig

相關問題