虚基类
程序员文章站
2022-06-05 13:46:51
...
前置:同名隐藏与二义性
情景解释:暑假结束了,一科作业都没有写的你慌了起来,而班里的大部分同学也都只写了一部分而已,所以不想欠下一点作业的你只好向多个人借作业抄以保证一科都不漏,当然啦,如果当中A同学和B同学都完成了C科作业,你肯定只用抄其中一份就OK了
虚基类:
- 需要解决的问题:当派生类从多个基类派生,而这些基类又共同基类,则在访问此共同基类中的成员时,将产生冗余,并有可能因冗余带来不一致性
- 虚基类声明:以virtual说明基类继承方式,例:class B1: virtual public B
- 作用:主要用来解决多继承时可能发生的对同一基类继承多次而产生的二义性问题,为最远的派生类提供唯一的基类成员,而不重复产生多次复制
- 注意:在第一级继承时就要将共同基类全部设计为虚基类
虚基类及其派生类构造函数:
- 建立对象时所指定的类称为最远派生类
- 虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的(这个原则和以前构造语法不同,一般来讲每个派生类只需要给它的直接派生类构造函数提供参数)
- 在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中为虚基类的构造函数列出参数。
- 如果未列出,则表示调用该虚基类的默认构造函数
- 在建立对象时,只有最远派生类的构造函数调用虚基类的构造函数,其他类对虚基类构造函数的调用被忽略
#include<iostream>
using namespace std;
class Base0
{
public:
Base0() { var0 = 0; }
Base0(int x): var0(x) {}
int var0;
};
class Base1: virtual public Base0
{
public:
Base1() { var1 = 0; }
Base1(int x): Base0(x) {}
int var1;
};
class Base2: virtual public Base0
{
public:
Base2() { var2 = 0; }
Base2(int x): Base0(x) {}
int var2;
};
class Derived: public Base1, public Base2
{
public:
Derived(int x, int y, int z): Base0(x), Base1(y), Base2(z) {}
int var;
};
class Text2: public Base1, public Base2
{
public:
Text2(int x): var0(x) {}
void Print() { printf("%d\n", var0); }
private:
int var0;
};
int main(void)
{
Derived d(2, 3, 4);
d.Base1::var0 = 2;
d.Base2::var0 = 3;
printf("%d\n", d.var0); //合法,其实派生类d只继承了唯一一个var0变量
printf("%d\n", d.Base1::var0);
printf("%d\n", d.Base2::var0); //输出结果:3 3 3
Text2 q(1000);
q.Base1::var0 = 3;
q.Base2::var0 = 2;
q.Print(); //合法,输出1000,因为派生类也定义了var0,所以基类的var0全部被隐藏,这个最多属于冗余问题
printf("%d\n", q.Base1::var0);
printf("%d\n", q.Base2::var0); //输出结果:2 2
return 0;
}
程序图表如下: