虚基类小思
程序员文章站
2022-06-08 18:16:37
...
虚基类的形式
虚基类就是在继承基类时,在继承类别(public、protect、private等)前加限定词virtual,形如:
class base{}//基类
class base_virtual:virtual public base{}//这就是虚基类的形式
虚基类存在的意义
在基类继承关系比较复杂的时候,基类成员的继承关系会引起混乱,例如:
此时,子类grandchild想继承parent中的int a ,但是该如何继承呢?具体通过child1还是child2,这个途径是不清楚的,因此定义了虚基类,使得他们的继承关系变得明确。
虚基类的具体继承方式
说明的代码如下:
#include<iostream>
using namespace std;
class par{
int n;
public:
par(){
a=2;cout<<"parent="<<a<<endl;}
protected:
int a;
};
class child1:virtual public par{
int n1;
public:
child1(){a+=5;cout<<"child1="<<a<<endl;}
};
class child2:virtual public par{
int n2;
public:
child2(){a+=8;cout<<"child2="<<a<<endl;}
};
class grandchild:public child1,public child2{
public:
grandchild(){cout<<"grandchild a ="<<a<<endl; }
};
int main(){
grandchild example;
return 0;
}
这里grandchild类在child1、child2类上继承,间接继承了par类,它继承的成员变量有n,n1,n2,并且只继承了一次,为了表征这种关系,特意在构造函数内建立了变量a。
- 在定义了grandchild类后,系统开始调用grandchild()构造函数,发现他的父类是child1、child2,便先跳转(按继承的顺序)到child1,因为child1在par类上继承,因此再跳到par类进行函数构造,因此,首先有:
parent=2
- par类构造结束,转到child1类进行构造,a继承自par,因此a=2+5=7,所以此时child1的构造函数中会输出:
child1=7
- 如果child1、child2不是虚函数,那么在运行child2的构造函数时,会返回它的继承父类par,重新构造一次,但现在我们有了virtual关键字,就不会这样重新构造,而是继续继承child1之后计算得到的a=7,因此,child2的构造函数会输出:
child2=15
- 在构造完grandchild继承的child1、child2之后,开始运行grandchild自身的构造函数,此时继承child2中的a=15,因此它的构造函数会输出:
grandchild a =15
(析构的话,方向相反。)
因此,总的程序输出结果为:
parent=2
child1=7
child2=15
grandchild a =15
//此处空行是因为grandchild构造函数中的endl...
总结
虚基类是解决类继承关系出现矛盾时一种高效的调整方法。