天天看點

C++菱形繼承+虛繼承

單繼承和多繼承

單繼承:一個派生類隻有一個直接基類。

(B的直接父類隻有A,是單繼承)

class AA
{
public:
    AA(int a=)
    :_a(a)
    {
        cout << "AA()" << endl;
    }

    int _a;
};

class BB : public AA
{
public:
    BB(int b=)
    :_b(b)
    {
        cout << "BB()" << endl;
    }

    int _b;
};
           

多繼承:一個派生類的直接基類至少有兩個。

(C類不僅繼承了A類,還繼承了B類,是多繼承)

class CC : public AA ,public BB
{
public:
    CC(int c=)
    :_c(c)
    {
        cout << "CC()" << endl;
    }

    int _c;
};
           

菱形繼承屬于多繼承。

#include<iostream>
#include<stdlib.h>
using namespace std;

class A
{
public:
    A(int a=)
    :_a(a)
    {
        cout << "A()" << endl;
    }

    int _a;
};

class B : public A
{
public:
    B(int b=)
    :_b(b)
    {
        cout << "B()" << endl;
    }

    int _b;
};

class C : public A 
{
public:
    C(int c=)
    :_c(c)
    {
        cout << "C()" << endl;
    }

    int _c;
};

class D : public B, public C
{
public:
    D(int d=)
    :_d(d)
    {
        cout << "D()" << endl;
    }

    int _d;
};

int main()
{
    D d;
    d._a;
}
           

對上面代碼進行編譯,發現不通過,錯誤如下:

C++菱形繼承+虛繼承

這個是菱形繼承存在的二義性的問題。

C++菱形繼承+虛繼承

從圖中可以看出來,在D類中B類和C類分别存了一份A類的成員變量,造成了資料備援的問題。

二義性問題可以通過指定類域進行通路,但是這樣太麻煩,而且資料備援的問題并沒有得到解決。針對這個問題C++引入了虛繼承。

虛繼承:繼承的前面加上virtual.

形如:class 派生類名:virtual 繼承方式 基類名

(virtual為關鍵字,聲明該基類為派生類的虛基類)

C++菱形繼承+虛繼承
#include<iostream>
#include<stdlib.h>
using namespace std;

class A
{
public:
    A(int a=)
        :_a(a)
    {
        cout << "A()" << endl;
    }

    int _a;
};

class B : virtual public A
{
public:
    B(int b=)
        :_b(b)
    {
        cout << "B()" << endl;
    }

    int _b;
};

class C : virtual public A 
{
public:
    C(int c=)
        :_c(c)
    {
        cout << "C()" << endl;
    }

    int _c;
};

class D : public B, public C
{
public:
    D(int d=)
        :_d(d)
    {
        cout << "D()" << endl;
    }

    int _d;
};

int main()
{
    D d;
}
           
C++菱形繼承+虛繼承

虛繼承的記憶體分布有所變化,這裡将公共的A類成員變量單獨存起來,以前存A類成員變量的地方存了虛基類的位址,這個位址存的是A類成員變量距派生類位址的偏移量。

雖然虛繼承解決了菱形繼承二義性和資料備援的問題,但是性能上會有所影響。

沒有使用虛繼承時,sizeof(d)=20;

使用虛繼承後,sizeof(d)=24.

繼續閱讀