C++的继承和派生(三)虚继承和虚基类、虚继承时的构造函数

虚继承和虚基类的概念

  • 多继承
    多继承是指从多个直接基类中产生派生类的能力,多继承的派生类继承了所有父类的所有的成员,但是多继承很容易造成命名冲突的问题,例如典型的菱形继承
    在这里插入图片描述

如上图所示,假设当类A中有一个成员变量a,那么在D类中直接访问就会产生歧义,因为编译器不知道成员变量 a 的来源途径是什么(A→B→D还是A→C→D)。不仅如此,类A在类D 中存在两份数据,那么构造D类的对象时,就必须对这两份数据经行初始化,此时来A 的构造函数就会调用两次。为了解决多继承时的成员冗余、重复和命名冲突的问题,C++提出了虚继承,使得在派生类中只保留一份间接基类的成员。(在上图中:A:间接基类,C,D:直接基类)

  • 虚继承:在继承方式前加上关键字 virtual 就表示虚继承
class A {
public:
	int m_a=1;
	A() {
		cout << "A的构造函数" << endl;
	}
};

class B:virtual public A  {
public:
	int m_b=2;

	B() {
		cout << "B的构造函数" << endl;
	}
};

class C :virtual public A {
public:
	int m_c=3;

	C() {
		cout << "C的构造函数" << endl;
	}
};

class D :public B , public C {
	int m_d=4;
public:
	void Display() {
		printf("a=%d,b=%d,c=%d,d=%d\n",m_a, m_b, m_c, m_d);
	}

	D() {
		cout << "D的构造函数" << endl;
	}
};

int main() {
	D d;
	d.Display();
	getchar();
	return 0;
}

运行结果

A的构造函数
B的构造函数
C的构造函数
D的构造函数
a=1,b=2,c=3,d=4

虚继承时的构造函数

  • 说明
    在虚继承时,构造函数的执行顺序与普通继承时不同,在最终的派生类的构造函数的初始化列表中,不管各个构造函数出现的顺序如何,编译器总是先定义虚基类的构造函数,再按照出现的顺序定义其他的构造函数,,如果没有虚继承,编译器会按照出现的顺序依次调用

补充:虚继承时的对象内存布局
在继承时,派生类会为每一个虚基类增加一个隐藏的虚基类指针(为了能够找到虚基类成员在派生类中的位置)。虚基类的成员会被排在最后(了解即可)

猜你喜欢

转载自blog.csdn.net/qq_47329614/article/details/106957708