C 虛繼承和虛繼承

2022-08-12 20:39:14 字數 1355 閱讀 2319

虛繼承是在多繼承中為了解決衝突而技術。學術一點來說,是指乙個指定的基類,在繼承體系結構中,將其成員資料例項共享給也從這個基類直接或間接派生的其他類。

虛繼承非常有用,可以避免多繼承的歧義和多重拷貝。

考慮有如下繼承結構。

b和c繼承a,d多繼承b、c,我們看以下**。

class a ;

class b :public a ;

class c :public a ;

class d :public b, public c ;

到這裡,可能聰明的讀者已經看出來有什麼問題了。如果我們對d進行例項化。

d d;

a& a = d;

這麼寫的話,編譯器會無情的報錯。例如vs2019就會說這是一種不明確的轉換。沒錯,因為按照上面的定義,d是乙個有歧義的類。因為d間接地繼承了兩次a(b繼承了,c繼承了,d又繼承了b和c),所以所有的d物件就會有兩個不同的由a派生的派生物件(b和c)。因此,嘗試直接對其進行引用,編譯器會一頭霧水,這個引用到底是想指向哪個a啊?究竟是 b::a 還是 c::a ?所以這樣是不對的。

當然,我們可以使用static_cast進行強制型別轉換,但是這不是我們今天學習的目標。

我們可以看到,我們不需要兩個a,不需要a被繼承兩次。我們只是需要乙個層次結構來說明a、b、c、d之間的關係。假如a是職業,b是銷售,c是經理,我們僅僅想表示d是乙個銷售經理。而不意味著d是兩個a,銷售經理是一種職業而不是兩種職業。而且從上面這個特殊的例子來看,b和c並沒有過載sayhi()這個函式,sayhi()繼承到d這裡仍是之前那套運作規律,所以我們也不需要兩份一模一樣的sayhi()。

於是,虛繼承便橫空出世來解決這個問題了。

我們如果這麼宣告繼承,

class a ;

// virtual

class b :public virtual a ;

class c :virtual public a ;

class d :public b, public c ;

這個a就是所說的虛基類。由於虛基類是多個派生類共享的基類,因此必須明確到底誰來初始化這個虛基類。c++標準規定,由最後派生的類來初始化虛基類。因此,對於間接繼承了虛繼類的類,也必須能直接訪問虛繼承來的祖先類,能夠訪問其虛函式表。

例如,之前的例子當中,b和c、d的建構函式初始化列表中都可以給出虛基類的初始化,但是只能由d的建構函式執行虛基類的初始化。

虛繼承和虛函式繼承

虛繼承主要用於菱形 形式的繼承形式 虛繼承是為了在多繼承的時候避免引發歧義,比如類 有個就是a,繼承了 c也繼承了 當 多繼承 時,就會有歧義產生了,所以要使用虛擬繼承避免重複拷貝。虛函式繼承是解決多型性的,當用基類指標指向派生類物件的時候,基類指標呼叫虛函式的時候會自動呼叫派生類的虛函式,這就是多...

c 虛函式和虛繼承

c 中,多型的實現需要虛函式,而虛函式主要包括兩部分,虛函式指標和虛函式表。基類將自己的一些函式設為虛函式,子類則需要在繼承基類後,重寫或者直接使用從基類的繼承下來的虛函式。基類自己會儲存乙份虛函式表,這個虛函式表含有指向基類虛函式的虛函式指標。當子類繼承基類後,同樣會將基類的虛函式表繼承下來,這樣...

c 多繼承和虛繼承

一 關於多繼承 菱形繼承 指的是b繼承a,c繼承a,d繼承b和c。下圖是菱形繼承的過程,以及各類的簡單的記憶體布局。菱形繼承存在的問題 間接基類的資料會出現多份導致訪問出錯,並且存在記憶體浪費 我們可以利用虛繼承來解決這一問題。二 虛繼承 虛繼承是物件導向程式設計中的一種技術,是指乙個指定的基類,在...