33.C++-虚基类

虚基类

当在多条继承路径上有一个公共的基类,在这些路径中的某几条汇合处,这个公共的基类就会产生多个实例(或多个副本),若只想保存这个基类的一个实例,可以将这个公共基类说明为虚基类。

  • 虚基类: 为了解决多重继承时,基类可能出现多次继承问题.

如下图所示:

 

如果未使用虚基类,那么D类会有两份类A的成员变量和函数,这在设计上来说,是多余的,因为D类只需要一个类A的成员变量和函数.

未使用虚基类-示例如下所示:

#include <iostream>
using namespace std;
class A
{
protected:
    int nv;
public://外部接口

    A(int n){ nv = n; cout << "Member of A" << endl; }//B0类的构造函数
    void fun(){ cout << "fun of A" << endl; }
};
class B : public A
{
    int nv1;
public:
    B(int a) :A(a){ cout << "Member of B" << endl; }
};
class C : public A
{
    int nv2;
public:
    C(int a) :A(a){ cout << "Member of C" << endl; }
};
class D :public B, public C
{
    int nvd;
public:
    D(int a) :B(a), C(a) {
        cout << "Member of D" << endl;

        // cout << nv << endl;    // 将会报错,编译器不知道nv是B类还是C类的.

        cout << B::nv << endl;
        cout << C::nv << endl;

        B::fun();
        C::fun();
    }
};
int main(void)
{
    D d(1);
    return 0;
}

打印如下所示:

 

为了解决继承下来的成员冗余问题,所以便有了虚基类,也就是虚继承.

虚继承就是在声明派生类的时候给基类加上virtual继承.如果有个派生类给基类加上了virtual继承,那么应当所有基类的直接派生类都应该声明virtual,否则也会出现多次继承问题

使用虚基类-示例如下所示:

#include <iostream>
using namespace std;
class A
{
protected:
    int nv;
public://外部接口

    A(int n){ nv = n; cout << "Member of A" << endl; }//B0类的构造函数
    void fun(){ cout << "fun of B0" << endl; }
};
class B : virtual public A
{public:
    B(int a) :A(a){ cout << "Member of B" << endl; }
};
class C : virtual public A
{public:
    C(int a) :A(a){ cout << "Member of C" << endl; }
};
class D :public B, public C
{public:
    D(int a) : A(a), B(a), C(a) {
        cout << "Member of D" << endl;
        cout << nv << endl;
        fun();
    }
};
int main(void)
{
    D d(1);
    return 0;
}

打印如下所示:

 

此时的类D就只有一份类A的成员和函数了.需要注意的是:

  • 如果虚基类的构造函数带有参数,那么需要在初始化列表对虚基类进行初始化,并且虚基类的其他派生类不会再对虚基类进行多次初始化.

比如我们将D类的构造函数改为:

D(int a) : A(200), B(1), C(1) {

        cout << "Member of D" << endl;
        cout << nv << endl;
        fun();
}

这时打印如下所示:

可以看到通过A(200)我们初始化nv为200后,并未被赋值回去

posted @ 2021-06-09 18:21  诺谦  阅读(203)  评论(0编辑  收藏  举报