C++虚基类

可以使用作用域分辨符来来存放不同数据、进行不同操作,但也可以通过虚基类来维护一个成员副本。将共同基类设置为虚基类,这时不同路径继承过来的同名数据成员在内存中就只有一个副本,同一个函数名也只有一个映射。

虚基类成员在派生过程中和派生类一起维护同一个内存数据副本,这一点其实很好理解。

我们先来看一下没有声明虚基类的程序:

#include <iostream>
using namespace std;

class Base0{
    public:
        int var0;
        void fun0(){cout<<"Member of Base0"<<endl;}
};

class Base1:public Base0{
    public:                                //新增外部接口
        int var1;
};

class Base2:public Base0{
    public:                                //新增外部接口
        int var2;
};

class Derived:public Base1,public Base2{
    public:                                //新增外部接口
        int var;
        void fun(){cout<<"Member of Derived"<<endl;}
};

int main(){
    Derived d;
    d.var0=2;
    d.fun0();
    return 0;
}

程序显然无法成功运行,错误原因:request for member 'var0'(fun0) is ambiguous(不明确的),因为Base1和Base2都有var0fun0(),程序不知道你调用的是哪一个类继承下来的,除非你用作用域分辩符来唯一标识,写成:

    d.Base1::var0=2;
    d.Base1::fun0();
    d.Base2::var0=3;
    d.Base2::fun0();

这样Base1和Base2类下的数据就分开存储了,当然我们也可以使用虚基类技术进行共同存储,也就是这几个类共用一个var0fun0副本,能节省不少内存空间。

虚基类的声明只是在类派生过程中使用virtual关键字,代码如下:

#include <iostream>
using namespace std;

class Base0{
    public:
        int var0;
        void fun0(){cout<<"Member of Base0"<<endl;}
};

class Base1:virtual public Base0{         
    public:                                //新增外部接口
        int var1;
};

class Base2:virtual public Base0{
    public:                                //新增外部接口
        int var2;
};

class Derived:public Base1,public Base2{
    public:                                //新增外部接口
        int var;
        void fun(){cout<<"Member of Derived"<<endl;}
};

int main(){
    Derived d;
    d.var0=2;                     //直接访问虚基类的数据成员
    d.fun0();                     //直接访问虚基类的函数成员
    return 0;
}

这样一来,程序就能成功运行:
这里写图片描述
这时的Derived类中,通过Base1,Base2继承来的基类Base0中成员var0fun0只有一份副本,改变var0的值,就相当于改变Base1,Base2中的var0的值了。

猜你喜欢

转载自blog.csdn.net/weixin_41656968/article/details/80853759