第四章:function語意學
4.2 虛擬成員函式
a) 單一繼承下的virtual function
乙個class只會有乙個virtual table
這個class自己定義的virtual function,它override了乙個可能存在的base class virtual function函式實體。
繼承自base class的函式實體。
乙個純虛函式實體。
b) 多重繼承下的virtual function
在多重繼承中實現virtual functions。其複雜度在於第二個以及之後的base class身上。例如:有如上派生關係,如果有:那麼第一行會將pbase指標調整以指向base2 subobject。否則的話,類似這種非多型應用都會失敗。而在第三行的時候,由於要呼叫derived的析構,所以this指標又會被調整到derived物件開頭。
其實現是運用了一種叫thunk的技術,在**裡面插了一小段彙編**,用來做兩件事情:調整this指標的位置,跳轉到virtual function的位置。
於是,對於多重繼承來說,有多少個base class,就有多少個vptr,分別指向多少張virtual table。每個virtual table的內容參見《深度探索c++物件模型》p165頁的圖。注意,由於base_1和derived class共享乙個virtual table,所以該virtual table內的內容最多。甚至包括了base_2::mumble。不過base_2::mumble的真正位址存放在base_2對應的virtual table中。所以想要通過derived class的指標條用mumble方法,需要利用thunk調整this指標,這就是下面三種情況的第2種。(注意,某base class的指標,new出來的物件是derived的,也不能呼叫其他base class的方法
)指標的型別是什麼,就使用那個基類相應的virtua table。
派生類和第乙個base class使用的是同乙個virtual table。
有三種情況,第二或者後繼的base class會影響到virtual functions的支援。這時候需要利用thunk調整this指標。
c) 虛擬繼承下的virtual functions由於point2d和point3d的起始位置不一樣,所以兩者之間的轉換也需要做this指標調整。
所以對於point3d object來說(編譯器是vc),有兩張virtual table,乙個是繼承下來的,裡面內容z()和析構函式變成了derived class的z()和析構。mumble()應該保持不變。另一長virtual table裡面多了乙個virtual base class object的offset,其餘一樣。(見《深度探索c++物件模型》p169頁的圖)
不過有些編譯器如gcc則是將這個offset加到第一張table中,於是gcc編譯器編譯的結果也只有一張virtual table。
《深度探索C 物件模型》讀書筆記(5)
純虛函式 在設計抽象基類時,需要注意以下幾點 1 不要將destructor宣告為pure virtual function 如果將destructor宣告為pure virtual function,則設計者一定得定義它。因為每乙個derived class destructor會被編譯器加以擴充...
《深度探索C 物件模型》讀書筆記(6)
物件的構造和解構 一般而言,我們會把object盡可能放置在使用它的那個程式區段附近,這樣做可以節省不必要的物件產生操作和銷毀操作。全域性物件 全域性物件的靜態初始化策略包括以下幾個步驟 1 為每乙個需要靜態初始化的物件產生乙個 sti 函式,內含必要的constructor呼叫操作或inline ...
讀書筆記 《深度探索c 物件模型》 (4)
第五章 構造,解構,拷貝語意學 5.2 繼承體系下的物件構造 a 虛擬繼承 如同下面的繼承情況 在這種情況下,vertex3d壓制了它的兩個父類對point constructor的呼叫,這個呼叫工作由vertext3d本身來完成。所以輸出為 b vptr初始化語意學 接著上面的例子 輸出為 雖然n...