c 虛繼承與繼承的差異

2021-08-09 20:48:39 字數 1590 閱讀 2841

前面一篇文章,說明了在c++ 虛繼承對基類構造函式呼叫順序的影響。經過仔細推敲,發現沒有徹底說清楚虛繼承與普通繼承之間的關係。所以用下面的文字再說明一下。

首先,重複一下虛擬繼承與普通繼承的區別有:

假設derived 繼承自base類,那麼derived與base是一種「is a」的關係,即derived類是base類,而反之錯誤;

假設derived 虛繼承自base類,那麼derivd與base是一種「has a」的關係,即derived類有乙個指向base類的vptr。

因此虛繼承可以認為不是一種繼承關係,而可以認為是一種組合的關係。因為虛繼承有著「繼承」兩個關鍵字,那麼大部分人都認為虛繼承與普通繼承的用法沒什麼太大的不同。由此用在繼承體系中,這種將虛繼承認為是普通繼承的危害更佳大。下面先用乙個例子來說明問題:

[cpp]

view plain

copy

class

base  

;  class

derived:

public

base  

;  

上面是普通繼承實現,在實際應用中,我們可以使用下面的**進行型別轉換:

[cpp]

view plain

copy

intmain(

intargc, 

const

char

* argv)    

編譯無錯誤,而且會得出正確的結果。其結果為:

base::base()!

derived::derived()!

base::printbase()!

derived::printderived()!

而將上面的普通繼承變成虛擬繼承,如下**:

[cpp]

view plain

copy

class

base1  

;  class

derived1:

virtual

public

base1  

;  int

main(

intargc, 

const

char

* argv)    

編譯上面的**,提示如下:

可以看到不能將基類通過static_cast轉換為繼承類。我們知道c++提供的強制轉換函式static_cast對於繼承體系中的類物件的轉換一般是可行的。那麼這裡為什麼就不可以了呢?還是需要從虛擬繼承的內部實現來說明問題。

virtual base class的原始模型是在class object中為每乙個有關聯的virtual base class加上乙個指標vptr,該指標指向virtual基類表。有的編譯器是在繼承類已存在的virtual table直接擴充匯入乙個virtual base class table。不管怎麼樣由於虛繼承已完全破壞了繼承體系,不能按照平常的繼承體系來進行型別轉換。

不管怎麼樣,虛繼承在型別轉換是一定要十分注意。不要輕易使用虛繼承,更不要在虛繼承的基礎上進行型別轉換,切記切記!

C 鑽石繼承與虛繼承

首先,何為鑽石繼承,顧名思義,在類的繼承過程中,繼承結構是乙個類似菱形 鑽石 的結構就屬於鑽石繼承,如下 這是乙個最簡單的鑽石繼承。實際上,在複雜的繼承表中,只要子類按不同的繼承路徑回溯到基類有菱形結構,均屬鑽石繼承。下面先看乙個例子,鑽石繼承在c 程式設計中帶來的問題。1 2 include3 u...

C 多重繼承與虛繼承

在派生類中對基類成員的訪問應該是唯一的。但是,在多繼承情況下,可能造成對基類中某個成員的訪問出現了不一致的情況,這時就稱對基類成員的訪問產生了二義性。派生類在訪問基類成員函式時,由於基類存在同名的成員函式,導致無法確定訪問的是哪個基類的成員函式,因此出現了二義性錯誤。例如 includeusing ...

C 多繼承與虛繼承

目錄 多繼承與虛繼承以及存在的問題 例子 虛繼承有了多繼承,虛繼承才會有意義 如果有個菱形結構的繼承,爺爺類為a,然後b,c是a的派生類,最後d是b和c的派生類,如果在a中有乙個成員變數a,d去呼叫就會出現訪問不明確,虛繼承就可以解決訪問不明確的這種問題 如果這樣繼承b,c虛繼承了a,virtual...