多繼承 與 多重繼承

weixin_34116110發表於2018-04-13

多繼承

多繼承是指一個子類繼承多個父類。多繼承對父類的個數沒有限制,繼承方式可以是公共繼承、保護繼承和私有繼承。不寫繼承方式,預設是私有繼承

多繼承下派生類的定義格式如下:

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” 的關係,並且能夠通過父類的指標對直接子類或間接子類進行相應的操作,子類物件可以給直接父類或間接父類的物件或引用賦值或初始化。

相關文章