C 繼承 3 多重繼承

2021-07-02 19:50:27 字數 3590 閱讀 3163

目錄

1.多重繼承中建構函式的呼叫順序

2.菱形繼承問題

2.1問題介紹

2.2解決方法

2.3預設建構函式問題

3.總結

多重繼承是c++的乙個特性,使得乙個類可以繼承自多個類。子類會根據所繼承的類的順序,來依次呼叫父類的建構函式。

例如,下面程式中,b的建構函式先於a的建構函式被呼叫。

#includeusing namespace std;

class a

~a() };

class b

~b() };

class c: public b, public a //注意這裡的繼承順序

~c() };

int main()

輸出:

b constructor called

a constructor called

c constructor called

c destructor called

a destructor called

b destructor called

注意:析構函式的呼叫順序與建構函式相反。

菱形繼承的問題出現在某個類的兩個父類擁有共同的基類。

例如,下面程式中,ta類會擁有person類的兩份資料成員拷貝,這會導致歧義性。

執行結果:

person::person(int) called

faculty::faculty(int) called

person::person(int) called

student::student(int) called

ta::ta(int ) called

存在的問題:

上述程式中,person類的構造函式呼叫了兩次。當物件ta1被銷毀時,person的析構函式也會被呼叫兩次。

物件ta1擁有person類的兩份資料成員,這會導致歧義。

使用virtual關鍵字。將faculty和student做為virtual基類來避免ta類中出現person的兩份拷貝。

#includeusing namespace std; 

class person

person()

}; class faculty : virtual public person

}; class student : virtual public person

}; class ta : public faculty, public student

}; int main()

輸出結果:

person::person() called

faculty::faculty(int) called

student::student(int) called

ta::ta(int) called

上述程式中,person類的建構函式只呼叫了一次。

需要注意非常重要的一點:2.2中例子,結果顯示物件ta1呼叫的是person的預設建構函式。

當使用virtual關鍵字時,預設呼叫的是祖父類的預設建構函式。即使父類顯式地呼叫了祖父類的帶引數的建構函式,也不會改變這個行為。

而如果我們把person的預設建構函式注釋起來,則編譯時會報錯。

visual studio2015報錯如下:

error c2512: 「person::person」: 沒有合適的預設建構函式可用

g++ 4.8.5 報錯如下:

error: no matching function for call to 'person::person()'

如何才能呼叫person的帶引數的建構函式?

必須在ta類中呼叫person的帶引數的建構函式。如下所示:

#includeusing namespace std;

class person

person() };

class faculty : virtual public person };

class student : virtual public person };

class ta : public faculty, public student };

int main()

執行結果:

person::person(int ) called

faculty::faculty(int ) called

student::student(int ) called

ta::ta(int ) called

一般來說,子類不允許直接呼叫祖父類的建構函式,而應該通過父類來呼叫。僅當使用了virtual時,才能呼叫祖父類建構函式。

#includeusing namespace std;

class a

void print() };

class b: public a};

class c: public a };

class d: public b, public c ;

int main()

編譯錯誤。類d中的print()函式有歧義。

visual studio2015編譯報錯:

error c2385: 對「print」的訪問不明確,note: 可能是「print」(位於基「a」中),note: 也可能是「print」(位於基「a」中)

將類b和c設定為虛繼承後(如下面兩行所示),則輸出結果為20。

class b: virtual publica

class c: virtual publica

參考例子2

#includeusing namespace std;

class a

void print() };

class b: virtual public a};

class c: virtual public a};

class d: public b, public c ;

int main()

執行結果:

編譯錯誤。類a中沒有定義預設建構函式。

當給a加上預設建構函式後:

a()

則輸出結果為:11

多重繼承 C 中的多重繼承

多重繼承是c 的一項功能,其中乙個類可以從多個類繼承。繼承類的建構函式以它們繼承的相同順序被呼叫。例如,在以下程式中,在a的建構函式之前呼叫b的建構函式。include using namespace std class a class b class c public b,public a not...

C 多重繼承 虛繼承

c 中的多繼承,建構函式處理並沒有問題,物件構造的時候按照繼承中宣告的順序呼叫多個父類的建構函式,析構函式同樣遵守單繼承中的原則。二意性問題 如果多基類中存在同名成員,會產生二意性的問題 比如,root1類中宣告doany 介面,root2類中也宣告了doany 介面,child多承繼root1和r...

C 多重繼承 環狀繼承

ambigous 二義性 模糊性 繼承定義虛基類 子類繼承父類的時候,在父類前加 virtual 基類 class beauty beauty string n,int a,double h,double w void setinfo string n,int a,double h,double w...