本文參照於狄泰軟體學院,唐佐林老師的——《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...