亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

 更新時間:2015年09月22日 16:31:20   投稿:goldensun  
這篇文章主要介紹了深入解析C++中類的多重繼承,包括多重繼承相關(guān)的二義性問題,需要的朋友可以參考下

C++類的多繼承
在前面的例子中,派生類都只有一個基類,稱為單繼承。除此之外,C++也支持多繼承,即一個派生類可以有兩個或多個基類。
多繼承容易讓代碼邏輯復(fù)雜、思路混亂,一直備受爭議,中小型項目中較少使用,后來的 Java、C#、PHP 等干脆取消了多繼承。想快速學(xué)習(xí)C++的讀者可以不必細讀。
多繼承的語法也很簡單,將多個基類用逗號隔開即可。例如已聲明了類A、類B和類C,那么可以這樣來聲明派生類D:

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


D是多繼承的派生類,它以共有的方式繼承A類,以私有的方式繼承B類,以保護的方式繼承C類。D根據(jù)不同的繼承方式獲取A、B、C中的成員,確定各基類的成員在派生類中的訪問權(quán)限。
多繼承下的構(gòu)造函數(shù)

多繼承派生類的構(gòu)造函數(shù)和單繼承類基本相同,只是要包含多個基類構(gòu)造函數(shù)。如:

D類構(gòu)造函數(shù)名(總參數(shù)表列): A構(gòu)造函數(shù)(實參表列), B類構(gòu)造函數(shù)(實參表列), C類構(gòu)造函數(shù)(實參表列){
 新增成員初始化語句
}


各基類的排列順序任意。

派生類構(gòu)造函數(shù)的執(zhí)行順序同樣為:先調(diào)用基類的構(gòu)造函數(shù),再調(diào)用派生類構(gòu)造函數(shù)?;悩?gòu)造函數(shù)的調(diào)用順序是按照聲明派生類時基類出現(xiàn)的順序。

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

#include <iostream>
using namespace std;
//基類
class BaseA{
protected:
 int a;
 int b;
public:
 BaseA(int, int);
};
BaseA::BaseA(int a, int b): a(a), b(b){}
//基類
class BaseB{
protected:
 int c;
 int d;
public:
 BaseB(int, int);
};
BaseB::BaseB(int c, int d): c(c), d(d){}
//派生類
class Sub: public BaseA, public BaseB{
private:
 int e;
public:
 Sub(int, int, int, int, int);
 void display();
};
Sub::Sub(int a, int b, int c, int d, int e): BaseA(a, b), BaseB(c, d), e(e){}
void Sub::display(){
 cout<<"a="<<a<<endl;
 cout<<"b="<<b<<endl;
 cout<<"c="<<c<<endl;
 cout<<"d="<<d<<endl;
 cout<<"e="<<e<<endl;
}
int main(){
 (new Sub(1, 2, 3, 4, 5)) -> display();
 return 0;
}

運行結(jié)果:

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

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

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

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

Sub obj;
obj.display();


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

應(yīng)該像下面這樣加上類名和域解析符:

Sub obj;
obj.BaseA::display();
obj.BaseB::display();


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

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

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

1) 兩個基類有同名成員

代碼如下所示:

class A
{
public:
 int a;
 void display();
};
class B
{
public:
 int a;
 void display ();
};
class C: public A, public B
{
public:
 int b;
 void show();
};

如果在main函數(shù)中定義C類對象cl,并調(diào)用數(shù)據(jù)成員a和成員函數(shù)display :

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


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

 cl.A::a=3; //引用cl對象中的基類A的數(shù)據(jù)成員a
 cl.A::display(); //調(diào)用cl對象中的基類A的成員函數(shù)display

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

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

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

將上面的C類聲明改為:

 class C: public A, public B
 {
  int a;
  void display();
 };


如果在main函數(shù)中定義C類對象cl,并調(diào)用數(shù)據(jù)成員a和成員函數(shù)display:

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


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

有些讀者可能對同名覆蓋感到不大好理解。為了說明問題,舉個例子,例如把中國作為基類,四川則是中國的派生類,成都則是四川的派生類?;愂窍鄬Τ橄蟮?,派生類是相對具體的,基類處于外層,具有較廣泛的作用域,派生類處于內(nèi)層,具有局部的作用域。若“中國”類中有平均溫度這一屬性,四川和成都也都有平均溫度這一屬性,如果沒有四川和成都這兩個派生類,談平均溫度顯然是指全國平均溫度。如果在四川,談?wù)摦數(shù)氐钠骄鶞囟蕊@然是指四川的平均溫度;如果在成都,談?wù)摦數(shù)氐钠骄鶞囟蕊@然是指成都的平均溫度。這就是說,全國的“平均溫度”在四川省被四川的“平均溫度”屏蔽了,或者說,四川的“平均溫度”在當?shù)仄帘瘟巳珖摹捌骄鶞囟取?。四川人最關(guān)心的是四川的溫度,當然不希望用全國溫度覆蓋四川的平均溫度。

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

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

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

代碼如下所示:

class N
{
public:
 int a;
 void display(){ cout<<"A::a="<<a<<endl; }
};
class A: public N
{
public:
 int al;
};
class B: public N
{
public:
 int a2;
};
class C: public A, public B
{
public:
 int a3;
 void show(){ cout<<"a3="<<a3<<endl; }
}
int main()
{
 C cl; //定義C類對象cl
 // 其他代碼
}

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

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

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



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


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

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

相關(guān)文章

  • C++時間函數(shù)整理詳解

    C++時間函數(shù)整理詳解

    C++中并沒有針對時間特意提供特定的時間類型,而是直接繼承了C語言的結(jié)構(gòu)以及函數(shù),因此在C++中使用時間函數(shù)需要引用<ctime>頭文件,這篇文章主要介紹了C++時間函數(shù)
    2022-10-10
  • C/C++混合編程之extern “C”的使用示例

    C/C++混合編程之extern “C”的使用示例

    這篇文章主要給大家介紹了關(guān)于C/C++混合編程之extern “C”使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • 了解C++編程中指定的異常和未經(jīng)處理的異常

    了解C++編程中指定的異常和未經(jīng)處理的異常

    這篇文章主要介紹了C++中指定的異常和未經(jīng)處理的異常,介紹了有關(guān)noexcept和terminate的作用,并結(jié)合了C++11標準的新特性,需要的朋友可以參考下
    2016-01-01
  • C++實現(xiàn)騎士走棋盤算法

    C++實現(xiàn)騎士走棋盤算法

    這篇文章主要為大家詳細介紹了C++實現(xiàn)騎士走棋盤算法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Opencv學(xué)習(xí)教程之漫水填充算法實例詳解

    Opencv學(xué)習(xí)教程之漫水填充算法實例詳解

    這篇文章主要給大家介紹了Opencv學(xué)習(xí)教程之漫水填充算法的相關(guān)資料,文中給出了詳細的示例代碼供大家參考學(xué)習(xí),對大家具有一定的參考價值,需要的朋友們下面跟著小編一起來學(xué)習(xí)學(xué)習(xí)吧。
    2017-06-06
  • C++實現(xiàn)簡單版通訊錄管理系統(tǒng)

    C++實現(xiàn)簡單版通訊錄管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C++實現(xiàn)簡單版通訊錄管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C++線性表深度解析之動態(tài)數(shù)組與單鏈表和棧及隊列的實現(xiàn)

    C++線性表深度解析之動態(tài)數(shù)組與單鏈表和棧及隊列的實現(xiàn)

    這篇文章主要為大家詳細介紹了C++實現(xiàn)動態(tài)數(shù)組、單鏈表、棧、隊列,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • C++ OpenCV學(xué)習(xí)之圖像金字塔與圖像融合詳解

    C++ OpenCV學(xué)習(xí)之圖像金字塔與圖像融合詳解

    圖像金字塔分為兩種:高斯金字塔和拉普拉斯金字塔。圖像金字塔在保持細節(jié)的條件下進行圖像融合等多尺度編輯操作非常有用。本文將利用圖像金字塔實現(xiàn)圖像融合,需要的可以參考一下
    2022-03-03
  • C++實現(xiàn)大數(shù)乘法算法代碼

    C++實現(xiàn)大數(shù)乘法算法代碼

    這篇文章主要介紹了C++實現(xiàn)大數(shù)乘法算法代碼的相關(guān)資料,需要的朋友可以參考下
    2015-03-03
  • C++實現(xiàn)LeetCode(75.顏色排序)

    C++實現(xiàn)LeetCode(75.顏色排序)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(75.顏色排序),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-07-07

最新評論