亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

深入解析C++中類的多重繼承

2020-05-23 14:14:14
字體:
來源:轉載
供稿:網友

這篇文章主要介紹了深入解析C++中類的多重繼承,包括多重繼承相關的二義性問題,需要的朋友可以參考下

C++類的多繼承

在前面的例子中,派生類都只有一個基類,稱為單繼承。除此之外,C++也支持多繼承,即一個派生類可以有兩個或多個基類。

多繼承容易讓代碼邏輯復雜、思路混亂,一直備受爭議,中小型項目中較少使用,后來的 Java、C#、PHP 等干脆取消了多繼承。想快速學習C++的讀者可以不必細讀。

多繼承的語法也很簡單,將多個基類用逗號隔開即可。例如已聲明了類A、類B和類C,那么可以這樣來聲明派生類D:

 

 
  1. class D: public A, private B, protected C{ 
  2. //類D新增加的成員 

D是多繼承的派生類,它以共有的方式繼承A類,以私有的方式繼承B類,以保護的方式繼承C類。D根據不同的繼承方式獲取A、B、C中的成員,確定各基類的成員在派生類中的訪問權限。

多繼承下的構造函數

多繼承派生類的構造函數和單繼承類基本相同,只是要包含多個基類構造函數。如:

 

 
  1. D類構造函數名(總參數表列): A構造函數(實參表列), B類構造函數(實參表列), C類構造函數(實參表列){ 
  2. 新增成員初始化語句 

各基類的排列順序任意。

派生類構造函數的執行順序同樣為:先調用基類的構造函數,再調用派生類構造函數?;悩嬙旌瘮档恼{用順序是按照聲明派生類時基類出現的順序。

下面的定義了兩個基類,BaseA類和BaseB類,然后用多繼承的方式派生出Sub類。

 

 
  1. #include <iostream> 
  2. using namespace std; 
  3. //基類 
  4. class BaseA{ 
  5. protected
  6. int a; 
  7. int b; 
  8. public
  9. BaseA(intint); 
  10. }; 
  11. BaseA::BaseA(int a, int b): a(a), b(b){} 
  12. //基類 
  13. class BaseB{ 
  14. protected
  15. int c; 
  16. int d; 
  17. public
  18. BaseB(intint); 
  19. }; 
  20. BaseB::BaseB(int c, int d): c(c), d(d){} 
  21. //派生類 
  22. class Sub: public BaseA, public BaseB{ 
  23. private
  24. int e; 
  25. public
  26. Sub(intintintintint); 
  27. void display(); 
  28. }; 
  29. Sub::Sub(int a, int b, int c, int d, int e): BaseA(a, b), BaseB(c, d), e(e){} 
  30. void Sub::display(){ 
  31. cout<<"a="<<a<<endl; 
  32. cout<<"b="<<b<<endl; 
  33. cout<<"c="<<c<<endl; 
  34. cout<<"d="<<d<<endl; 
  35. cout<<"e="<<e<<endl; 
  36. int main(){ 
  37. (new Sub(1, 2, 3, 4, 5)) -> display(); 
  38. return 0; 

運行結果:

 

 
  1. a=1 
  2. b=2 
  3. c=3 
  4. d=4 
  5. e=5 

從基類BaseA和BaseB繼承來的成員變量,在 Sub::display() 中都可以訪問。

命名沖突

當兩個基類中有同名的成員時,就會產生命名沖突,這時不能直接訪問該成員,需要加上類名和域解析符。

假如在基類BaseA和BaseB中都有成員函數 display(),那么下面的語句是錯誤的:

 

 
  1. Sub obj; 
  2. obj.display(); 

由于BaseA和BaseB中都有display(),系統將無法判定到底要調用哪一個類的函數,所以報錯。

應該像下面這樣加上類名和域解析符:

 

 
  1. Sub obj; 
  2. obj.BaseA::display(); 
  3. obj.BaseB::display(); 

通過這個舉例可以發現:在多重繼承時,從不同的基類中會繼承一些重復的數據。如果有多個基類,問題會更突出,所以在設計派生類時要細致考慮其數據成員,盡量減少數據冗余。

C++多重繼承的二義性問題

多重繼承可以反映現實生活中的情況,能夠有效地處理一些較復雜的問題,使編寫程序具有靈活性,但是多重繼承也引起了一些值得注意的問題,它增加了程序的復雜度,使 程序的編寫和維護變得相對困難,容易出錯。其中最常見的問題就是繼承的成員同名而產生的二義性(ambiguous)問題。

如果類A和類B中都有成員函數display和數據成員a,類C是類A和類B的直接派生類。分別討論下列3種情況。

1) 兩個基類有同名成員

代碼如下所示:

 

  1. class A 
  2. public
  3. int a; 
  4. void display(); 
  5. }; 
  6. class B 
  7. public
  8. int a; 
  9. void display (); 
  10. }; 
  11. class C: public A, public B 
  12. public
  13. int b; 
  14. void show(); 
  15. }; 

如果在main函數中定義C類對象cl,并調用數據成員a和成員函數display :

 

 
  1. C cl; 
  2. cl.a=3; 
  3. cl.display(); 

由于基類A和基類B都有數據成員a和成員函數display,編譯系統無法判別要訪問的是哪一個基類的成員,因此程序編譯出錯。那么,應該怎樣解決這個問題呢?可以用基類名來限定:

 

 
  1. cl.A::a=3; //引用cl對象中的基類A的數據成員a 
  2. cl.A::display(); //調用cl對象中的基類A的成員函數display 

如果是在派生類C中通過派生類成員函數show訪問基類A的display和a,可以不 必寫對象名而直接寫

 

 
  1. A::a = 3; //指當前對象 
  2. A::display(); 

2) 兩個基類和派生類三者都有同名成員

將上面的C類聲明改為:

 

 
  1. class C: public A, public B 
  2. int a; 
  3. void display(); 
  4. }; 

如果在main函數中定義C類對象cl,并調用數據成員a和成員函數display:

 

 
  1. C cl; 
  2. cl.a = 3; 
  3. cl.display(); 

此時,程序能通過編譯,也可以正常運行。請問:執行時訪問的是哪一個類中的成員?答案是:訪問的是派生類C中的成員。規則是:基類的同名成員在派生類中被屏蔽,成為“不可見”的,或者說,派生類新增加的同名成員覆蓋了基類中的同名成員。因此如果在定義派生類對象的模塊中通過對象名訪問同名的成員,則訪問的是派生類的成員。請注意:不同的成員函數,只有在函數名和參數個數相同、類型相匹配的情況下才發生同名覆蓋,如果只有函數名相同而參數不同,不會發生同名覆蓋,而屬于函數重載。

有些讀者可能對同名覆蓋感到不大好理解。為了說明問題,舉個例子,例如把中國作為基類,四川則是中國的派生類,成都則是四川的派生類?;愂窍鄬Τ橄蟮模缮愂窍鄬唧w的,基類處于外層,具有較廣泛的作用域,派生類處于內層,具有局部的作用域。若“中國”類中有平均溫度這一屬性,四川和成都也都有平均溫度這一屬性,如果沒有四川和成都這兩個派生類,談平均溫度顯然是指全國平均溫度。如果在四川,談論當地的平均溫度顯然是指四川的平均溫度;如果在成都,談論當地的平均溫度顯然是指成都的平均溫度。這就是說,全國的“平均溫度”在四川省被四川的“平均溫度”屏蔽了,或者說,四川的“平均溫度”在當地屏蔽了全國的“平均溫度”。四川人最關心的是四川的溫度,當然不希望用全國溫度覆蓋四川的平均溫度。

如果在四川要查全國平均溫度,一定要聲明:我要查的是全國的平均溫度。同樣,要在派生類外訪問基類A中的成員,應指明作用域A,寫成以下形式:

 

 
  1. cl.A::a=3; //表示是派生類對象cl中的基類A中的數據成員a 
  2. cl.A::display(); //表示是派生類對象cl中的基類A中的成員函數display 

3) 類A和類B是從同一個基類派生的

代碼如下所示:

 

 
  1. class N 
  2. public
  3. int a; 
  4. void display(){ cout<<"A::a="<<a<<endl; } 
  5. }; 
  6. class A: public N 
  7. public
  8. int al; 
  9. }; 
  10. class B: public N 
  11. public
  12. int a2; 
  13. }; 
  14. class C: public A, public B 
  15. public
  16. int a3; 
  17. void show(){ cout<<"a3="<<a3<<endl; } 
  18. int main() 
  19. C cl; //定義C類對象cl 
  20. // 其他代碼 

在類A和類B中雖然沒有定義數據成員a和成員函數display,但是它們分別從類N繼承了數據成員a和成員函數display,這樣在類A和類B中同時存在著兩個同名的數據成員a和成員函數display。它們是N類成員的拷貝。類A和類B中的數據成員a代表兩個不同的存儲單元,可以分別存放不同的數據。在程序中可以通過類A和類B的構造函數去調用基類N的構造函數,分別對類A和類B的數據成員a初始化。

怎樣才能訪問類A中從基類N繼承下來的成員呢?顯然不能用

 

 
  1. cl.a = 3; cl.display(); 

 

 
  1. cl.N::a = 3; cl. N::display(); 

因為這樣依然無法區別是類A中從基類N繼承下來的成員,還是類B中從基類N繼承下來的成員。應當通過類N的直接派生類名來指出要訪問的是類N的哪一個派生類中的基類成員。如

 

 
  1. cl.A::a=3; cl.A::display(); //要訪問的是類N的派生類A中的基類成員 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧洲亚洲妇女av| 亚洲人成77777在线观看网| 一本一道久久a久久精品逆3p| 亚洲最新在线视频| 国产经典一区二区| 欧美在线视频一区二区| 91在线观看免费高清完整版在线观看| 亚洲一区二区三区777| 色偷偷偷亚洲综合网另类| 亚洲美女在线视频| 97精品伊人久久久大香线蕉| 国产免费一区视频观看免费| 黑人巨大精品欧美一区免费视频| 亚洲国产精品999| 亚洲图片欧美午夜| 日韩视频免费中文字幕| 欧美裸体视频网站| 国产精品视频专区| 欧美激情区在线播放| 亚洲视频777| 国产一区二区动漫| 在线视频日本亚洲性| 亚洲最新视频在线| 欧美极品第一页| 久久久成人的性感天堂| 欧美中文字幕第一页| 中文字幕在线精品| 亚洲欧美制服中文字幕| 亚洲精品中文字幕有码专区| 亚洲精品mp4| 欧美在线播放视频| 亚洲欧美成人一区二区在线电影| 国产69精品久久久久9999| 亚洲国内高清视频| 久久精品福利视频| 成人激情视频小说免费下载| 国产精品自拍小视频| 在线视频日本亚洲性| 久久综合九色九九| 久久理论片午夜琪琪电影网| 亚洲一级免费视频| 中文字幕日韩有码| 好吊成人免视频| 国产精品日韩精品| 一本久久综合亚洲鲁鲁| 96pao国产成视频永久免费| 欧美高清视频一区二区| 国产乱肥老妇国产一区二| 性欧美xxxx| 欧美视频在线观看免费| 国产成人久久久精品一区| 91精品国产自产在线观看永久| 中文字幕亚洲国产| 国产69精品久久久久99| 亚洲精品一区二三区不卡| 国产精品久久久久9999| 日韩av免费在线观看| 88国产精品欧美一区二区三区| 成人黄色片网站| 美日韩精品免费视频| 精品久久久久久久久国产字幕| 精品国产区一区二区三区在线观看| 久热爱精品视频线路一| 亚洲天堂男人的天堂| 日韩精品亚洲元码| 成人羞羞国产免费| 97精品国产aⅴ7777| 国产精品wwwwww| 亚洲春色另类小说| 欧美精品免费在线| 亚洲精品视频免费在线观看| 最近2019中文字幕mv免费看| 午夜精品视频在线| 亚洲最大的成人网| 国产美女精品视频免费观看| 欧美日韩国产中字| 亲子乱一区二区三区电影| 日韩中文字幕亚洲| 懂色av一区二区三区| 中文字幕亚洲第一| 国产成人精品999| 日韩欧美高清在线视频| 91大神在线播放精品| 成人免费观看49www在线观看| 欧美午夜精品久久久久久浪潮| 成人性生交大片免费看视频直播| 亚洲精品资源在线| 国产欧美欧洲在线观看| 日韩高清电影好看的电视剧电影| 日韩精品视频在线免费观看| 2019中文字幕免费视频| 国产精品尤物福利片在线观看| 亚洲一区二区三区xxx视频| 在线观看日韩av| www欧美xxxx| 国产精品福利小视频| 中文字幕日韩欧美精品在线观看| 一区二区三区国产在线观看| 亚洲精品456在线播放狼人| 亚洲成人激情在线| 欧美激情视频给我| 日韩在线视频观看正片免费网站| 国产精品久久久久久五月尺| 亚洲色图在线观看| 日韩在线视频中文字幕| 国产精品久久久久久久久男| 日韩欧美在线国产| 亚洲天堂av在线播放| 97视频在线观看免费高清完整版在线观看| 精品欧美激情精品一区| 亚洲free性xxxx护士hd| 51精品在线观看| 国产成人+综合亚洲+天堂| 亚洲综合大片69999| 日本精品一区二区三区在线播放视频| 国产精品久久久久久久一区探花| 亚洲精品久久久久久久久久久久久| 中文字幕精品一区二区精品| 欧美日韩国产黄| 亚洲人a成www在线影院| 日韩在线观看网站| 国产一区二区丝袜| 亚洲欧洲免费视频| 日韩精品视频在线观看网址| 精品国产一区二区三区久久久狼| 亚洲图片欧洲图片av| 欧美高清性猛交| 国产精品久久9| 日韩中文综合网| 久久久久久久久久久免费| 在线视频欧美性高潮| 成人黄色在线播放| 色琪琪综合男人的天堂aⅴ视频| 欧美中文字幕在线视频| 亚洲jizzjizz日本少妇| 97久久精品国产| 国产精品夫妻激情| 日韩电影免费观看在线| 国产精国产精品| 精品国产一区av| 一区二区福利视频| 久久久久久久久久久亚洲| 在线看福利67194| 亚洲精品98久久久久久中文字幕| 麻豆精品精华液| 日韩免费黄色av| 国产香蕉精品视频一区二区三区| 91理论片午午论夜理片久久| 久久男人的天堂| 久久久中精品2020中文| 久久香蕉频线观| 日本一欧美一欧美一亚洲视频| 亚洲毛茸茸少妇高潮呻吟| 欧美大荫蒂xxx| 欧美日韩国产123| 国产欧美精品xxxx另类| 欧美大胆a视频| 最近更新的2019中文字幕| 久久综合伊人77777| 国产成人精品av在线| 亚洲欧美日韩精品久久奇米色影视| 日韩在线观看av| 精品亚洲一区二区三区四区五区| 欧美精品做受xxx性少妇|