1. 程式人生 > >C++ 多重繼承和虛繼承 記憶體分佈

C++ 多重繼承和虛繼承 記憶體分佈

現在考慮一下怎麼去實現從top1到left的靜態轉換,同時要想到,我們並不知道top1是否指向一個Bottom型別的物件,或者是指向一個AnotherBottom型別的物件。所以這辦不到!這個重要的偏移依賴於top1執行時的型別(Bottom則20,AnotherBottom則24)。編譯器將報錯:

?
1 2 error: cannot convert from base `Top' to derived type `Left' via virtual base `Top'

因為我們需要執行時的資訊,所以應該用一個動態轉換來替代實現:

?
1 Left* left = <b>dynamic_cast<</b>Left*<b>></b>(top1);

可是,編譯器仍然不滿意:

?
1 2 error: cannot dynamic_cast `top' (of type `class Top*') to type `class Left*' (source type is not polymorphic)

(注:polymorphic多型的

問題在於,動態轉換(轉換中使用到typeid)需要top1所指向物件的執行時型別資訊。但是,如果你看看這張圖,你就會發現,在top1指向的位置,我們僅僅只有一個integer (a)而已。編譯器沒有包含指向Top的虛擬指標,因為它不認為這是必需的。為了強制編譯器包含進這個vptr指標,我們可以給Top增加一個虛擬的析構器:

?
1 2 3 <b>class</b> Top { <b>public</b>: <span><b>
virtual</b> ~Top() {}</span> <b>int</b> a; };

這個修改需要指向Top的vptr指標。Bottom的新佈局是

layout of Bottom

(當然類似的其它類也有一個新的指向Top的vptr指標)。現在編譯器為動態轉換插進了一個庫呼叫:

?
1 left = __dynamic_cast(top1, typeinfo_for_Top, typeinfo_for_Left, -1);

這個函式__dynamic_cast定義在stdc++庫中(相應的標頭檔案是cxxabi.h);引數為Top的型別資訊,Left和Bottom(通過vptr.Top),這個轉換可以執行。 (引數 -1 標示出Left和Top之間的關係現在還是未知)。更多詳細資料,請參考tinfo.cc 的具體實現 。