多繼承 與 多重繼承
多繼承
多繼承是指一個子類繼承多個父類。多繼承對父類的個數沒有限制,繼承方式可以是公共繼承、保護繼承和私有繼承。不寫繼承方式,預設是私有繼承。
多繼承下派生類的定義格式如下:
class A
{
…
};
class B
{
…
};
class C : <繼承方式> public A, <繼承方式> public B
{
…
};
按照繼承的規定,派生類 C 的成員包含了基類 A、B 中成員以及該類本身的成員。
派生類建構函式執行順序是先執行所屬基類的建構函式,再執行派生類本身建構函式,處於同一層次的各基類建構函式的執行順序取決於定義派生類時所指定的各基類順序,與派生類建構函式中所定義的成員初始化列表的各項順序無關。
下面通過一個例子來說明派生類建構函式的構成及其執行順序:
#include <iostream.h>
class B1
{
public:
B1(int i)
{
b1 = i;
cout<<"建構函式 B1."<<i<< endl;
}
void print()
{
cout<<"B1.print()"<<b1<<endl;
}
private:
int b1;
};
class B2
{
public:
B2(int i)
{
b2 = i;
cout<<"建構函式 B2."<<i<< endl;
}
void print()
{
cout<<"B2.print()"<<b2<<endl;
}
private:
int b2;
};
class B3
{
public:
B3(int i)
{
b3 = i;
cout<<"建構函式 B3."<<i<<endl;
}
int getb3()
{
return b3;
}
private:
int b3;
};
class A : public B2, public B1 // 冒號之後是類派生表, 表的順序決定基類建構函式呼叫的順序, 解構函式的呼叫順序正好相反
{
public:
A(int i, int j, int k, int l):B1(i), B2(j), bb(k) // A 的引數列表必須包含後面繼承的所有基類的引數
{
a = l;
cout<<"建構函式 A."<<a<<endl;
}
void print()
{
B1::print();
B2::print();
cout<<"A.print()"<<a<<","<<bb.getb3()<<endl;
}
private:
int a;
B3 bb;
};
void main()
{
A aa(1, 2, 3, 4);
aa.print();
}
該程式的輸出結果為:
建構函式 B2.2
建構函式 B1.1
建構函式 B3.3
建構函式 A.4
B1.print()1
B2.print()2
A.print()4,3
在該程式中,作用域運算子 ::
用於解決作用域衝突的問題。在派生類 A 中的 print() 函式的定義中,使用了 B1::print;
和 B2::print();
語句分別指明呼叫哪一個類中的 print() 函式,否則會出現二義性問題。
如果是基類和派生類中出現同名函式,不存在二義性問題,規定派生類的成員將支配基類中的同名成員,即派生類的物件只會使用派生類的該函式。
當一個派生類 C 從多個基類派生(B1、B2...),而這些基類又有一個共同的基類 A,則對該 A 類中宣告的成員進行訪問時,也可能會出現二義性。應以作用域 B1::
或 B2::
等來限定。
由於二義性的原因,一個類不可以從同一個類中直接繼承一次以上,例如:
class A : public B, public B // 這是錯誤的
{
…
}
多重繼承
當 B 類從 A 類派生,C 類從 B 類派生,此時稱為多重繼承。
當例項化子類時,會首先依次呼叫所有基類的建構函式,最後呼叫該子類的建構函式;銷燬該子類時則相反,先呼叫該子類的解構函式,再依次呼叫所有基類的解構函式。
無論繼承的層級有多少層,子類都可以與其直接父類或間接父類構成 “is a” 的關係,並且能夠通過父類的指標對直接子類或間接子類進行相應的操作,子類物件可以給直接父類或間接父類的物件或引用賦值或初始化。
相關文章
- C++ 多級繼承與多重繼承:程式碼組織與靈活性的平衡C++繼承
- 繼承與多型繼承多型
- odoo 繼承(owl繼承、web繼承、view繼承)Odoo繼承WebView
- 多繼承繼承
- 聊聊iOS中的多繼承和多重代理iOS繼承
- java繼承與多型Java繼承多型
- 說說C++多重繼承C++繼承
- YTU-OJ-多重繼承繼承
- 多重繼承及虛繼承中物件記憶體的分佈繼承物件記憶體
- day23:單繼承&多繼承&菱形繼承&__init__魔術方法繼承
- 原型,繼承——原型繼承原型繼承
- 菱形繼承,虛繼承繼承
- JavaScript 的繼承與多型JavaScript繼承多型
- Javascript的繼承與多型JavaScript繼承多型
- C#如何實現多重繼承C#繼承
- python 基礎之繼承、重寫、多繼承Python繼承
- C++繼承詳解:共有(public)繼承,私有(private)繼承,保護(protected)繼承C++繼承
- 繼承與派生繼承
- 繼承和多型繼承多型
- 多型和繼承多型繼承
- 三種繼承的方法:public 繼承/private繼承/protected繼承詳解及區別繼承
- Javascript繼承4:潔淨的繼承者—-原型式繼承JavaScript繼承原型
- Javascript繼承2:建立即繼承—-建構函式繼承JavaScript繼承函式
- Java 繼承與多型實驗Java繼承多型
- 繼承繼承
- python3 筆記20.類的呼叫和多重繼承(多重繼承MRO方法解析順序)Python筆記繼承
- C++繼承一之公有繼承C++繼承
- JS原型繼承和類式繼承JS原型繼承
- Maven 聚合與繼承Maven繼承
- Maven聚合與繼承Maven繼承
- 繼承與組合繼承
- Java:類與繼承Java繼承
- 繼承與介面 (轉)繼承
- C++中公有繼承、保護繼承、私有繼承的區別C++繼承
- 公有繼承、私有繼承和保護繼承之間的對比繼承
- 繼承+多型+抽象類繼承多型抽象
- Castle 多繼承選擇AST繼承
- Scala多繼承以及AOP繼承