C++ 派生类成员的标识与访问——虚基类及其派生类构造函数

虚基类的使用非常方便,简单,这是由于程序中所有类使用的都是自动生成的默认构造函数。如果虚基类声明有非默认的(即带参的)构造函数,并且没有声明默认形式的构造函数。这时,在整个继承关系中,直接或者间接继承虚基类的所有派生类,都必须在构造函数的成员初始化列表中列出对虚基类的初始化。

【例】

cpp 复制代码
class B0
{
public:
	B0(int v):v0(v){}//非默认构造函数
	int v0;
	void fun0()
	{
		cout << "基类B0的成员" << endl;
	}
};

class B1 :virtual public B0
{
public:
	B1(int v):B0(v){}//非默认构造函数
	int v1;
};

class B2 :virtual public B0
{
public:
	B2(int v) :B0(v) {}//非默认构造函数
	int v2;
};

class D :public B1, public B2
{
public:
	D(int v):B0(v),B1(v),B2(v){}//非默认构造函数
	int v;
	void fun()
	{
		cout << "派生类D的成员" << endl;
	}
};

int main()
{
	D d(1);
	d.v0 = 2;
	d.fun0();
	return 0;
}

运行结果:

分析:

在建立D对象d时,通过D来的构造函数的初始化列表,不仅调用了虚基类的构造函数B0(),对从B0继承的成员v0进行了初始化,而且还调用了直接基类B1和B2的构造函数B1()和B2(),而B1()和B2()的初始化列表中也都有对基类B0的初始化。这样,对于虚基类继承来的v0是否初始化了3次呢?

对于这个问题,我们完全不用担心,C++编译器会处理这个问题。先称建立对象时所指定的类称为当时的最远派生类。在建立一个对象时,如果这个对象中含有从虚基类继承来的成员时,则虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。而且,只有最远派生类的构造函数会调用虚基类的构造函数,该派生类的其他基类对虚基类构造函数的调用都会被自动忽略。

例如上述代码中的B0是派生类B1和B2的虚基类,主函数中建立的最远派生类D的对象d中含有从虚基类继承来的成员v0,这时,虚基类B0的成员v0是由最远派生类D的构造函数通过调用虚基类B0的构造函数进行初始化的。此时,该派生类D的其他基类B1和B2对虚基类B0的构造函数的调用被自动忽略。

总结:

构造一个类的对象的一般顺:

(1)如果该类有直接或者间接的虚基类,则先执行虚基类中的构造函数。

(2)如果该类有其他基类,则按照它们在继承声明列表中出现的次序,分别执行它们的构造函数,但在构造过程中,不再执行它们的虚基类的构造函数。

(3)按照在类定义中出现的顺序,对派生类中新增的成员对象进行初始化。对于类类型的成员对象,如果出现在构造函数的初始化列表中,则以其中指定的参数执行构造函数,如未出现,则执行默认构造函数;对于基本数据类型的成员对象,如果出现在构造函数的初始化列表中,则使用其中指定的值为其赋初值,否则什么也不做。

(4)执行构造函数函数体。

相关推荐
flying robot1 小时前
js在浏览器执行原理
开发语言·javascript·ecmascript
dhxhsgrx4 小时前
PYTHON训练营DAY25
java·开发语言·python
君鼎5 小时前
C++设计模式——单例模式
c++·单例模式·设计模式
风逸hhh6 小时前
python打卡day25@浙大疏锦行
开发语言·python
刚入门的大一新生6 小时前
C++初阶-string类的模拟实现与改进
开发语言·c++
小冯的编程学习之路7 小时前
【软件测试】:推荐一些接口与自动化测试学习练习网站(API测试与自动化学习全攻略)
c++·selenium·测试工具·jmeter·自动化·测试用例·postman
chxii8 小时前
5java集合框架
java·开发语言
老衲有点帅8 小时前
C#多线程Thread
开发语言·c#
C++ 老炮儿的技术栈8 小时前
什么是函数重载?为什么 C 不支持函数重载,而 C++能支持函数重载?
c语言·开发语言·c++·qt·算法