上述部落格給出了以下結論:
每個類都有虛指標和虛表;
如果不是虛繼承,那麼子類將父類的虛指標繼承下來,並指向自身的虛表(發生在物件構造時)。有多少個虛函式,虛表裡面的項就會有多少。多重繼承時,可能存在多個的基類虛表與虛指標;
如果是虛繼承,那麼子類會有兩份虛指標,乙份指向自己的虛表,另乙份指向虛基表,多重繼承時虛基表與虛基表指標有且只有乙份。
我覺的上述部落格中結論有些不妥,自己做了實驗進行驗證,記錄如下:
新增新虛函式
首先看一下普通繼承下,子類中定義新的虛函式會發生什麼:
子類b中沒有定義新虛函式:
子類b中定義新虛函式:
紅色框區域可知,新定義的虛函式和基類的虛函式儲存於乙個虛函式表,虛函式指標個數沒有改變。
再看一下虛繼承:
對比第一幅圖和這幅圖,可知虛繼承中會多乙個vbptr指標,它不是虛函式表指標。
為什麼這裡會出現vbptr,因為虛基類派生出來的類中,虛基類的物件不在固定位置(應該是在尾部),需要乙個中介才能訪問虛基類的物件.所以子類需要有乙個vbptr,對應的table中需要有一項指向虛基類.
虛繼承下,子類中定義新的虛函式:
對比第二幅圖和這幅圖,可知虛繼承下新增新的虛函式,會新新增新的虛函式表和虛函式指標,即基類的虛函式表中的函式是不增加的。
至此,可知:虛基類的虛函式表是不能加入新虛函式的,而普通基類的虛函式表是可以增加新的虛函式。
在子類中沒有增加新的虛函式時,虛函式表指標不變;
當子類中增加新的函式時,虛繼承的子類會增加乙個虛函式表用於儲存新的虛函式,故會多乙個虛函式表指標。
非虛多重繼承:
非虛多重繼承會將所有基類的虛函式表繼承下來。新增加的虛函式會增加到繼承順序第一的基類的虛函式表中。
多重虛繼承:
由於定義了新的虛函式而兩個基類都是虛繼承,所以需要新建虛函式表:故共有兩個基類虛函式表指標,乙個新的虛函式表指標。
鑽石繼承:
從前面實驗可知:b、c均有兩個虛函式表指標
對於d:由於虛基類的虛函式表只會存在乙份,所以d會有乙個a類的虛函式表指標,並有b、c基類的虛函式表指標。共3個指標。
虛基類指標vbptr和虛函式指標vfptr
1.問題 多重繼承 派生類物件中記憶體重複 訪問衝突 記憶體浪費 2.解決 對出現多份的資料在最近的繼承前加viture 3.虛繼承時,虛基類指標vbptr指向虛基類表vbtable,虛基類表中存放的就是資料相對於虛基類指標的偏移,從而根據偏移找到資料 vbptr vbtable vbtable 中...
虛基類 虛函式和純虛基類
首先看乙個例子 class base class child1 public base class child2 public base void main else p print 函式呼叫的時候,檢視虛表,根據p的位址首先從虛表裡面查詢要呼叫的函式 這裡呼叫child2的print 函式 ret...
C 虛函式 虛繼承 虛基類 多型 智慧型指標
簡記如下 1,什麼是虛函式 基類中被virtual關鍵字修飾的成員函式 基類希望被派生類重新定義 而不是被繼承 普通繼承 的函式 作用 實現多型。通過繼承基類中的虛函式,在子類中過載實現不同操作 2,什麼是虛繼承 虛擬繼承 d繼承自b和c,b和c都繼承自a,這時可以將b和c對a的繼承定義為虛繼承。用...