C 物件導向 21 多繼承語法和菱形繼承問題

2021-10-06 05:27:08 字數 3374 閱讀 4578

本篇來學習下c++中的多繼承,一般來說多繼承不建議使用,因為會很容易帶來問題。專案中使用的話,需要注意。還有乙個菱形繼承和菱形繼承帶來的問題和如何解決。

1.多繼承的語法

c++中支援多繼承,例如有兩個父類base1和base2,乙個子類sun, 現在子類要同時繼承兩個父類,語法格式如下

多繼承語法格式:class 子類 : 繼承方式 父類1, 繼承方式 父類2

#include using namespace std;

class base1

;class base2

;class sun : public base1, public base2

;void test01()

int main()

上面**在test01中這種寫法是不對,編譯器會報錯。

因為編譯器不知道這行**是想呼叫base1這個父類中的m_a還是 base2這個父類中的m_a.

2.多繼承問題解決

這種情況就需要新增作用域來解決。實際工作中,如果要繼承多個父類,有時候不同父類是不同人員開發的,很有可能存在同名的成員變數和函式,這個時候就需要小心通過這種新增作用域的方式來訪問成員屬性和方法。

3.菱形繼承

菱形繼承的概念:

1)兩個派生類繼承同乙個基類

2)又有某乙個類同時繼承這兩個派生類

這種繼承關係叫菱形繼承,也叫鑽石繼承。

上圖四張圖中心點,分別用線段連線起來就像乙個菱形,所以這種繼承關係叫菱形繼承。

4.菱形繼承的問題

把上面這個羊駝的例子用**繼承寫出來,然後看看有什麼問題

#include using namespace std;

//動物基類

class animal;

//羊類

class sheep : public animal{};

//駝類

class camel : public animal{};

//羊駝類

class sheepcamel : public sheep, public camel{};

void test01()

int main()

其中在sc.m_age = 18這行會報錯,遇到了前面多繼承的問題,編譯器提示,不明確的錯誤。根據前面多繼承問題的解決方法,我們需要新增作用域,也就是分別給羊下m_age賦值,和駝下m_age賦值。

#include using namespace std;

//動物基類

class animal;

//羊類

class sheep : public animal{};

//駝類

class camel : public animal{};

//羊駝類

class sheepcamel : public sheep, public camel{};

void test01()

int main()

執行輸出

sc.sheep::m_age = 18

sc.camel::m_age = 28

press any key to continue . . .

解決了m_age不明確的報錯,現在問題又來了。就是這是繼承,但是m_age有兩份資料,我們認為這個資料是重複,浪費了記憶體開銷。實際上,我們只需要乙份m_age這個資料就可以,下面可以使用關鍵字virtul,使用虛繼承方式解決資料重複的問題。

#include using namespace std;

//動物基類

class animal;

//羊類

class sheep : public virtual animal{};

//駝類

class camel : public virtual animal{};

//羊駝類

class sheepcamel : public sheep, public camel{};

void test01()

int main()

注意上面**中,在羊類和駝類繼承animal類中,使用了虛繼承,關鍵字是virtual。本篇暫時不討論這個virtual的知識,使用了虛繼承之後,在test01中,分別對羊和駝的成員屬性m_age賦值,那麼程式會使用最後一次賦值的值。可以看執行**輸出。

下面通過工具來看看這個繼承關係,然後嘗試解釋一下為什麼只需要乙份m_age,這裡面原理是什麼。

1)先通過vs自帶開發工具,檢視當前繼承關係

開始選單下找到vs2015或者vs2017 下的 vs 開發人員命令提示工具,開啟cd到當前cpp**的資料夾路徑

2)單類繼承關係圖如下

先來解釋這兩個紅圈單詞的含義

vbptr=> virtual base pointer, 虛基類指標

vbtable => virtual base table, 虛基類表

這裡面vbptr這個指標會指向vbtable

3)分支sheep裡面vbptr如何指向vbtable

上面三個分析步驟,分別意思是

1)sheep這個類根據vbptr找到了上面 標註數字1旁邊這個vbtable.

2)  在這個虛基表第二行,數字8表示偏移量

3)在數字3中,旁邊這個0表示這個時候vbptr的偏移量是0,加上8等於8,就會找到序號為8這個m_age成員變數。

同理,駝類也是這三個步驟,根據vbptr加上對應偏移量在vbtable中找到了m_age這個成員變數。

整個過程解釋了,使用同乙份資料m_age的原理。

單獨

PY21 單繼承多繼承菱形繼承

init 魔術方法 構造方法 觸發時機 例項化物件,初始化的時候觸發 功能 為物件新增成員 引數 引數不固定,至少乙個self引數 返回值 無 class myclass definit self print 11 self.name 張婕 print 22 print 33 obj myclass...

C 多繼承 菱形繼承 虛繼承

b和c都單繼承了a d繼承了b和c 是多繼承 有兩個或兩個以上的基類就是多繼承 class a public int ma class b public a public int mb class c public a public int mc class d public b,public c ...

物件導向 多繼承

class master object def init self self.kongfu 古法煎餅果子配方 例項變數,屬性 def make cake self 例項方法,方法 print 古法 按照 s 製作了乙份煎餅果子.self.kongfu def dayandai self print ...