天天看点

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.

继续阅读