2010-11-11 27 views
2

如題介紹了,我有3類:如何消除具有多重繼承的基類中的變量副本?

#include <iostream> 

using namespace std; 

class first 
{ 
protected : 
int data; 
public : 
first() 
    :data(1) 
{ 
    // empty 
} 

}; 

class second : public first 
{ 
protected : 
double x; 
public : 
second() 
    :first() 
{ 
    // empty 
} 
}; 

class combine : public first, public second 
{ 
public : 
combine() 
{ 
    // empty 
} 

}; 

int main() 
{ 
combine c; 
cout << sizeof(c) << endl; 

return 0; 
} 

當我檢查的sizeof(第一)爲4,其道理給我。但我不知道爲什麼sizeof(second)是16(我假設4 + 8 = 12!= 16),sizeof(combine)是24(4 + 4 + 8 = 16!= 24)。任何人都可以幫我解釋一下嗎? 此外,當從「第一」和「第二」「結合」多重繼承,我意識到,其大小包括從「第一」和「第二」類既數據(int)的;這是浪費記憶。有沒有辦法解決這個問題,即讓'第一'和'第二'共享'數據'的一個副本?

+0

您可能對[棧交換建議]感興趣(http://area51.stackexchange.com/proposals/11464/code-review?referrer=aWNm_PdciyFqjFW8CUacGw2「代碼評論」)。 – greatwolf 2011-01-13 10:03:19

回答

5

這是虛擬繼承是。爲了保持first被複制,你到處(直接)派生從first一類,你需要繼承虛擬的,所以你必須:

class second : public virtual first { // ... 

class combine : public virtual first, public second { // ... 
+0

非常感謝傑裏;) – Chan 2010-11-11 23:50:00

3

貌似對齊方式設置爲8,這意味着8以上的每個尺寸四捨五入爲8的倍數。8以下的尺寸四捨五入爲8,4,2或1.

例如

  • 首先:整數= 4
  • 第二:INT +雙= 4 + 8 = 12,向上舍入到16
  • 合併:INT +第二= 4 + 16 = 20,向上舍入到24 。

是的,第一個::數據被複制到組合中。使用虛擬繼承(請參閱其他答案)來解決這個問題。或者調整你的繼承關係。

這樣做是爲了增加內存訪問時間,但需要花費額外的內存。

如果您不能騰出額外的內存,請查看編譯器魔術,將對齊設置爲較低的值。幸運的是,這很少需要。

+1

注:只是爲了明確。編譯器允許向類中添加填充。通常這樣做是爲了將對象與特定的邊界對齊,以便對象陣列很好地適應插槽,並且對訪問很有效。 – 2010-11-11 22:44:44

+0

非常感謝;) – Chan 2010-11-11 23:49:40

+0

@Martin感謝您的評論! – Sjoerd 2010-11-12 11:59:16