虚基类
- 对于前面同名隐藏和二义性的例子,在内存中,派生类对象c同时拥有两个a的空间。这两个a可以分别通过B1和B2调用基类A的构造函数进行初始化,能够存放不同的数值;也可以使用作用域操作符通过直接基类进行区分,分别进行访问。但是在大多数情况下,我们不需要两个同名副本,只需要保留一个即可,C++提供了虚基类技术来解决此问题。
- 在前面的例子中,当我们定义一个派生类对象c时,它会构造B1类,B2类,B1,B2类都会有一个父类,因此A类被构造了两次。在c中,A中的数据成员a有两个副本,A中的成员函数fun0()也有两个映射。一般可以将共同基类A设置为虚基类,这时从不同路径继承过来的同名数据成员在内存中就只有一个空间,同一个函数名也只有一个映射,在构造派生类对象c时,A类只会构造一次。
- class B1:virtual public A{}; class B2:virtual public A{};
- 虚基类并不是将基类声明为虚基类,只是在类的派生过程中使用了virtual关键字。
#include <iostream>
using namespace std;
class A{
public:
int a;
void fun0()
{
cout<<"A function is called."<<endl;
}
A(){ cout<<"construct A"<<endl; }
~A(){ cout<<"destruct A"<<endl; }
};
class B1:virtual public A{
public:
int b1;
B1(){ cout<<"construct B1"<<endl; }
~B1(){ cout<<"destruct B1"<<endl; }
};
class B2:virtual public A{
public:
int b2;
B2(){ cout<<"construct B2"<<endl; }
~B2(){ cout<<"destruct B2"<<endl; }
};
class C:public B1,public B2{
public:
int b1;
C(){ cout<<"construct C"<<endl; }
~C(){ cout<<"destruct C"<<endl; }
void fun()
{
cout<<"C function is called."<<endl;
}
};
int main()
{
C c;
c.a=10; //只有一个副本,不存在二义性访问问题
c.fun0();
return 0;
}
运行结果: