2012-10-31 191 views
9

以下代碼的問題是從書約C++虛擬繼承

#include <iostream> 
using namespace std; 
class X{}; 
class Y: public virtual X{}; 
class Z: public virtual X{}; 
class A: public Y, public Z{}; 

int main() 
{ 
    cout<<sizeof(X)<<" "<<sizeof(Y)<<" "<<sizeof(Z)<<" "<<sizeof(A)<<endl; 
    return 0; 
} 

以我計算機(Windows,VS2010) 「C++對象模型內部」,則輸出爲:

我這裏還有我的問題

1的sizeof(X)= 1

書中說當X類型生成兩個實例時,比如說xa和xb。編譯會在A中插入一個字節,以便xa和xb可以具有不同的地址。我不太明白原因。

2,的sizeof(Y)= 4

通過使用虛擬繼承,我們將有一個額外的虛擬指針?我想這可能與多態中的虛擬指針不同。任何人都可以給我Y的內存佈局嗎?

謝謝!

+0

每個問題一個問題請 –

+0

第一個問題,檢查:http://stackoverflow.com/questions/621616/c-what-is-the-size-of-an- rq = 1 –

+1

我認爲你的主要問題是,因爲Y使用虛擬繼承來從非多態類X派生,而Y本身是非多態的,所以虛擬繼承本身會導致Y有一個V表,因此它的大小是4 .. – CashCow

回答

6
  1. 編譯新的炭類時是空的,所以它可以產生不同的對象
  2. 的sizeof(Y)= 4,因爲它是虛擬如果在屬性 - > C/C++/Command中使用visual studio use/d1reportAllClassLayout生成對象佈局 類Y對象佈局將在Visual上工作室:
  3. 書「裏面C++對象模型」由Stanley B.李普曼解釋這個非常好


     class Y size(4): 
      +--- 
      0  | {vbptr} 
      +--- 
      +--- (virtual base X) 
      +---
Y::[email protected]: 0 | 0 1 | 4 (Yd(Y+0)X)

vbi: class offset o.vbptr o.vbte fVtorDisp X 4 0 4 0
1

空類的sizeof總是返回1.這是一個空類的單個空字節。

A持有在虛擬表中的兩個條目, 一個用於Y 其他對於z

所以的sizeof兩個指針即8.

Y和Z都保持在具有X的單個條目他們的虛擬表,因此尺寸爲4

+0

我沒有在這裏看到稱爲B和C的類 – CashCow

1

的目的將包括ÿ對象中,Z-對象(按該順序),並且僅one X對象(由Y和Z中的指針引用),因爲Y和Z都是從X繼承的,這意味着當多重繼承發揮作用時,只有一個X對象將在子類中實例化。 A仍然有兩個對象(一個Y,一個Z),因此sizeof = 8(因爲它們都有sizeof = 4)。但Y和Z中指向X對象的指針都將指向相同的地址。

繼承樹的樣子:

X 
/\ 
Y Z 
\/
    A 
0

類-must-至少有1個字節的原因是說,我們有十數組如果它們是0字節,那麼& array [1]的地址與& array [3]的地址相同,這是沒人會想到的,會破壞代碼,如果你必須編寫代碼來檢查代碼,通常不會造成干擾任何意義。

Y就應該僅僅是

static void* virtual_ptr1 //note this is in virtual table and cannot be edited 

你能想到的虛函數表(虛擬指針類和虛擬函數)爲靜態變量,你不能用手/代碼編輯(或至少不應該)。把它想象成編譯器保留的靜態變量

+1

我喜歡這個解釋,原因是sizeof(X)= 1 – Junjie