C++编程入门(二) 互动版

虚基类

还是上面的二义性问题2,Child类通过两条路径,产生了爷爷类Base的多个实例,例如通过Child的对象,可以访问到Base类的两个不同的数据成员b,一个是通过Base1类继承来的,一个是通过Base2类继承来的。虚基类的作用就是让Child只有一个Base类的实例。

使用虚基类的继承称为虚拟继承。虚基类是相对于子类而言的,所以虚基类本身定义不需要修改,只是子类在继承的时候加关键字virtual

#include <iostream>
using namespace std;
class Base
{
    public:
        void func(){cout<<"Base func"<<endl;}
        int b;
};
class Base1:virtual public Base
{
    public:
        void func(){cout<<"Base1 func"<<endl;}
};
class Base2:virtual public Base
{
    public:
        void func(){cout<<"Base2 func"<<endl;}
};
class Child:public Base1,public Base2
{
    public:
        int func(){return Base1::b+Base2::b};
};
void main()
{
    Child c;
    c.Base1::b=8;
    c.Base2::b=16;
    cout<<"Base1 b="<<c.Base1::b<<endl;
    cout<<"Base2 b="<<c.Base2::b<<endl;
    c.Base1::func();
    c.Base2::func();
    c.Base::func();
}

注意第9和第14行,在继承方式Public前面的关键字,说明了这是虚基类继承。注意输出结果为:

Base1 b=16

Base2 b=16

Base1 func

Base2 func

Base func

前两行输出,b的值都是16,说明了Child对象c中只有一个Base类的实例。还有最后一行输出,通过c.Base::func(),调用到了Base类的函数,也说明Child对象c中只有一个Base类的实例。因为如果是两个Base实例的话,编译器就不知道是Base1中继承来的,还是Base2中继承来的了。

虚基类的构造函数

注意构造函数的调用顺序

1.先基类,后子类

2.有多个基类,先虚基类,后非虚基类

3.有多个虚基类,按照定义时的顺序依次构造

4.虚基类的构造函数只执行依次。(这就是Child对象c中只有一个Base类的实例)