C++中虚基类
程序员文章站
2022-06-08 18:27:24
...
虚基类
虚基类概念
虚基类是为了防止多重继承时,“孙辈”派生类派生产生对“爷爷辈”类产生多个冗余的数据而定义的概念。
与正常继承自基类的区别
如下面图示:
A是虚基类,B1和B2虚继承自A,D继承B1和B2,D中的数据就是来自A,B1,B2中的数据而无重复冗余。
而没有使用虚继承,D中的数据就包括了两份A类的数据。
虚基类例子
#include <iostream>
using namespace std;
class A// 声明为基类A,注意这里A类并不包含虚函数
{
int va;//默认为私有成员
public://外部接口
A(int n){ va = n; cout << "Member of A" << endl; }//A类的构造函数
void fun(){ cout << "fun of A" << endl; }
};
class B1 :virtual public A
{
int vb1;
public:
B1(int a) :A(a){ cout << "Member of B1" << endl; }
};
class B2 :virtual public A
{
int vb2;
public:
B2(int a) :A(a){ cout << "Member of B2" << endl; }
};
class D :public B1, public B2
{
int vd;
public:
D(int a) :A(a), B1(a), B2(a){ cout << "Member of D" << endl; }
void fund(){ cout << "fun of D" << endl; }
};
int main(void)
{
D d(1);
d.fund();
d.fun();
return 0;
}
执行结果:
Member of A
Member of B1
Member of B2
Member of D
fun of D
fun of A
在这里D只获得一次A中的va变量,如果没有虚基类继承,那么D在B1,B2中分别继承一次。
注意:
(1) 一个类在同一类的“族谱”中既可以是虚基类身份,也可以是非虚基类身份。
(2) 在孙子辈类及以后的类(如上面提到的D和D以后的类)的对象中,同名的虚基类(A)只产生一个虚基类对象,而某个非虚基类产生各自的对象。
(3) 虚基类子对象是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。在这里D对象生成时,A的子对象构造是由B2类的构造函数初始化产生。
(4) 最远派生类是指在继承结构中建立对象时所指定的类。
(5) 派生类的构造函数的成员初始化列表中必须列出对虚基类构造函数的调用;如果未列出,则表示使用该虚基类的缺省构造函数。
(6) 从虚基类直接或间接派生的派生类中的构造函数的成员初始化列表中都要列出对虚基类构造函数的调用。但仅仅用建立对象的最远派生类的构造函数调用虚基类的构造函数,而该派生类的所有基类中列出的对虚基类的构造函数的调用在执行中被忽略,从而保证对虚基类子对象只初始化一次。
(7) 在一个成员初始化列表中同时出现对虚基类和非虚基类构造函数的调用时,虚基类的构造函数先于非虚基类的构造函数执行。