目錄
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...