天天看點

C++ 對象的内 存布局(下)

(注:看本文的時候由于宿舍快斷電了,來不及細看,是以怕自己忘記,先貼出來.不排除文章有錯誤,大家自己測試一下.)

下面我們再來看看,發生重複繼承的情況。所謂重複繼承,也就是某個基類被間接地重複繼承了多次。

下圖是一個繼承圖,我們重載了父類的f()函數。

其類繼承的源代碼如下所示。其中,每個類都有兩個變量,一個是整形(4位元組),一個是字元(1位元組),而且還有自己的虛函數,自己overwrite父類的虛函數。如子類D中,f()覆寫了超類的函數, f1() 和f2() 覆寫了其父類的虛函數,Df()為自己的虛函數。

<a href="http://images.cnblogs.com/cnblogs_com/rollenholt/201204/201204270023277713.png"></a>

下面是對于子類執行個體中的虛函數表的圖:

我們可以看見,最頂端的父類B其成員變量存在于B1和B2中,并被D給繼承下去了。而在D中,其有B1和B2的執行個體,于是B的成員在D的執行個體中存在兩份,一份是B1繼承而來的,另一份是B2繼承而來的。是以,如果我們使用以下語句,則會産生二義性編譯錯誤:

D d;

d.ib = 0; //二義性錯誤

d.B1::ib = 1; //正确

d.B2::ib = 2; //正确

注意,上面例程中的最後兩條語句存取的是兩個變量。雖然我們消除了二義性的編譯錯誤,但B類在D中還是有兩個執行個體,這種繼承造成了資料的重複,我們叫這種繼承為重複繼承。重複的基類資料成員可能并不是我們想要的。是以,C++引入了虛基類的概念。

虛拟繼承的出現就是為了解決重複繼承中多個間接父類的問題的。鑽石型的結構是其最經典的結構。也是我們在這裡要讨論的結構:

上述的“重複繼承”隻需要把B1和B2繼承B的文法中加上virtual 關鍵,就成了虛拟繼承,其繼承圖如下所示:

上圖和前面的“重複繼承”中的類的内部資料和接口都是完全一樣的,隻是我們采用了虛拟繼承:其省略後的源碼如下所示:

在檢視D之前,我們先看一看<b>單一虛拟繼承</b>的情況。下面是一段在VC++2003下的測試程式:(因為VC++和GCC的記憶體而局上有一些細節上的不同,是以這裡隻給出VC++的程式,GCC下的程式大家可以根據我給出的程式自己仿照着寫一個去試一試):

其運作結果如下(我結出了GCC的和VC++2003的對比):

<b></b>

<a href="http://images.cnblogs.com/cnblogs_com/rollenholt/201204/201204270023287812.png"></a>

這裡,大家可以自己對比一下。關于細節上,我會在後面一并再說。

下面的測試程式是看子類D的記憶體布局,同樣是VC++ 2003的(因為VC++和GCC的記憶體布局上有一些細節上的不同,而VC++的相對要清楚很多,是以這裡隻給出VC++的程式,GCC下的程式大家可以根據我給出的程式自己仿照着寫一個去試一試):

<a href="http://images.cnblogs.com/cnblogs_com/rollenholt/201204/20120427002329942.png"></a>

關于虛拟繼承的運作結果我就不畫圖了(前面的作圖已經讓我産生了很嚴重的厭倦感,是以就偷個懶了,大家見諒了)

在上面的輸出結果中,我用不同的顔色做了一些标明。我們可以看到如下的幾點:

1)無論是GCC還是VC++,除了一些細節上的不同,其大體上的對象布局是一樣的。也就是說,先是B1(黃色),然後是B2(綠色),接着是D(灰色),而B這個超類(青藍色)的執行個體都放在最後的位置。

2)關于虛函數表,尤其是第一個虛表,GCC和VC++有很重大的不一樣。但仔細看下來,還是VC++的虛表比較清晰和有邏輯性。

3)VC++和GCC都把B這個超類放到了最後,而VC++有一個NULL分隔符把B和B1和B2的布局分開。GCC則沒有。

4)VC++中的記憶體布局有兩個位址我有些不是很明白,在其中我用紅色标出了。取其内容是-4。接道理來說,這個指針應該是指向B類執行個體的記憶體位址(這個做法就是為了保證重複的父類隻有一個執行個體的技術)。但取值後卻不是。這點我目前還并不太清楚,還向大家請教。

5)GCC的記憶體布局中在B1和B2中則沒有指向B的指針。這點可以了解,編譯器可以通過計算B1和B2的size而得出B的偏移量。

C++這門語言是一門比較複雜的語言,對于程式員來說,我們似乎永遠摸不清楚這門語言背着我們在幹了什麼。需要熟悉這門語言,我們就必需要了解C++裡面的那些東西,需要我們去了解他後面的記憶體對象。這樣我們才能真正的了解C++,進而能夠更好的使用C++這門最難的程式設計語言。

==============================================================================

本文轉自被遺忘的部落格園部落格,原文連結:http://www.cnblogs.com/rollenholt/archive/2012/04/27/2472867.html,如需轉載請自行聯系原作者

繼續閱讀