類的繼承 被遺棄的多重繼承

2021-08-20 08:49:50 字數 3469 閱讀 7215

本文參照於狄泰軟體學院,唐佐林老師的——《c++深度剖析教程》

關聯知識:virtual虛函式,繼承

問題:c++中是否允許乙個類繼承自多個父類?如果可以,那麼會出現什麼問題呢?如果不可以,為什麼?

我們在單繼承的語法基礎上,再繼承兩個父類,試試編譯是否能通過。

class derived : public basea,

public baseb,

public basec

;

發現可以通過編譯,那麼我們可以確定c++中支援多重繼承的**。也就是多重繼承也有單重繼承的特性。

1. 乙個子類可以擁有多個父類

2. 子類擁有所有父類的成員變數

3. 子類繼承所有父類的成員函式

4. 子類物件可以當做任意父類物件使用

問題:多重繼承會出現什麼問題嗎?

通過多重繼承得到的物件可能擁有「不同的位址」!

示例**:

#include 

#include

using

namespace

std;

class basea

int geta()

};class baseb

int getb()

};class derived : public basea, public baseb

int getc()

void print()

};int main()

else

cout

<< "pa = "

<< pa << endl;

cout

<< "pb = "

<< pb << endl;

cout

<< "paa = "

<< paa << endl;

cout

<< "pbb = "

<< pbb << endl;

return

0;}

輸出結果:

沒有解決方案!!!多重繼承可能產生冗餘的成員,我們設想一下這種情況。

docter類繼承了teacher和stduent這兩個類。這兩個父類繼承了people類中的函式時,那麼在呼叫父類函式時,將會呼叫哪個父類的函式呢?

當我們呼叫了這個函式時,編譯器會報錯。原因就是編譯器不知道到底應該呼叫哪個類的print()函式。產生錯誤。

而這種資料冗餘問題就是當多重繼承關係出現閉合時發生!

問題:我們如何解決這個問題呢?

思路:我們曾經在繼承中遇到同名覆蓋的問題。當時的解決方案是使用virtual關鍵字使父類的同名函式程式設計虛函式。那麼我們是否可以用相同的方法解決呢?

示例**:虛繼承

#include 

#include

using namespace std;

class people

void print()

};class teacher : virtual

public people

};class student : virtual

public people

};class doctor : public teacher, public student

};int main()

輸出結果:

name = delphi, age = 33

用虛繼承的方法能夠解決資料冗餘的問題

1. 使得中間層父類不再關心頂層父類的初始化

2. 最終子類必須直接呼叫頂層父類的建構函式

但是問題是:當架構設計中需要繼承時,無法確定使用直接繼承還是虛繼承!

多重繼承可能產生多個虛函式表

示例**:

#include 

#include

using

namespace

std;

class basea

};class baseb

};class derived : public basea, public baseb

;int main()

輸出結果:

sizeof(d) = 8

using pa to call funca()…

basea::funca()

using pb to call funcb()…

baseb::funcb()

using pb to call funcb()…

basea::funca()

pa = 0xbff7094c

pb = 0xbff70950

pbe = 0xbff7094c

分析:

1. 由baseb* pbe = (baseb*)pa;可知,我們是想把pa物件強制型別轉換為baseb*型別。但是從輸出basea::funca()結果來看,pbe依然指向的是pa物件。

2. 從列印pa,pb,pbe位址來看,pbe的確依然指向了pa所指的位址,並沒有強制型別轉換成功。所以輸出的是basea類的成員函式。

實際上這種強制型別轉換是c語言中的方式,在c++中並不是用於多繼承的情況。那麼如何解決呢?c++為我們提供了新式型別轉換。

用於繼承的強制型別轉換關鍵字為:dynamic_cast。

53 被遺棄的多重繼承

c 支援編寫多重繼承的 乙個子類可以擁有多個父類,子類擁有所有父類的成員變數,子類繼承所有父類的成員函式,子類物件可以當作任意父類物件使用。多重繼承的本質與單繼承相同。include include using namespace std class basea int geta class bas...

C 54 被遺棄的多重繼承 下

輸出 sizeof d 8 using pa to call funca basea funca using pb to call funcb baseb funcb using pbc to call funcb baseb funcb using pbe to call funcb basea ...

C 53 被遺棄的多重繼承 (上)

問題 c 中是否允許乙個類繼承自多個父類?class derived public base a,public base b,public base c include using namespace std class basea int geta class baseb int getb cla...