C++关于虚基类、构造函数、析构函数、成员对象的两个程序浅析

预备博客:

C++虚继承中构造函数和析构函数顺序问题以及原理
C++派生类含有成员对象构造函数析构函数顺序
C++虚基类成员可见性

程序一如下:

#include<iostream>
using namespace std;
class A {
public:
	A(int a) :x(a) { cout << "A constructor..." << x << endl; }
	int f() { return ++x; }
	~A() { cout << "destructor A..." << endl; }
private:
	int x;
};
class B :public virtual A {
private:
	int y;
	A Aobj;
public:
	B(int a, int b, int c) :A(a), y(c), Aobj(c) { cout << "B constructor..." << y << endl; }
	int f() {
		A::f();
		Aobj.f();
		return ++y;
	}
	void display() { cout << A::f() << "\t" << Aobj.f() << "\t" << f() << endl; }
	 ~B() { cout << "destructor B..." << endl; }
};
class C :public B {
public:
	C(int a, int b, int c) :B(a, b, c), A(0) { cout << "C constructor..." << endl; }
};
class D :public C, public virtual A  { 
public:
	D(int a, int b, int c) :C(a, b, c), A(c) { cout << "D constructor..." << endl; }
	~D() { cout << "destructor D...." << endl; }
};
int main()
{
	D d(7, 8, 9);
	d.f();
	d.display();
	return 0;
}

同时还要注意调用函数的时候顺序为从右往左

解析:首先我们调用D的构造函数,发现D虚继承了A,直接继承了C,间接继承了B,B中含有成员对象Aobj,因此构造函数的调用顺序为:
A(9)【首先调用虚基类的构造函数,输出A constructor...9
A(9)【接下来调用B的构造函数,因为B含有成员对象Aobj,所以先调用Aobj的构造函数,输出A constructor...9
B(7,8,9)【运行B的构造函数,输出B constructor...9
C(7,8,9)【运行C的构造函数,输出C constructor...
D(7,8,9)【运行D的构造函数,输出D constructor...
d.f()【因为d中没有f方法,因此我们在其基类中找,发现其间接基类B和虚基类A中含有方法f,但是B中的方法优先级更高,因此访问的是B中的方法,B中的方法f会调用A中的方法fA::x=10,然后调用Aobj.f(),则Aobj.x=10,然后y=10
d.dispaly()【运行B的方法,因为输出的时候是从右往左输出的,所以先调用B中的方法f,此时A::x=11Aobj.x=11y=11,同时函数返回11,然后再调用Aobj.f(),返回12,再调用A::f(),返回12,输出12 12 11
~D()【开始析构,调用顺序和调用构造函数的顺序相反,先是D,然后再调用C的,调用B的,调用Aobj的,调用A的,输出destructor D....
~C()【没有输出】
~B()【输出destructor B...
~A()【输出destructor A...
~A()【输出destructor A...

运行结果:

在这里插入图片描述

程序二如下:

#include <iostream>
using namespace std;
class Base1
{
public:
	Base1()
	{
		cout << "class Base1!" << endl;
	}
};
class Base2
{
public:
	Base2()
	{
		cout << "class Base2!" << endl;
	}
};
class Level1 :public Base2, virtual public Base1
{
public:
	Level1()
	{
		cout << "class Level1!" << endl;
	}
};
class Level2 : public Base2, virtual public Base1
{
public:
	Level2()
	{
		cout << "class Level2!" << endl;
	}
};
class TopLevel :public Level1, virtual public Level2
{
public:
	TopLevel()
	{
		cout << "class TopLevel!" << endl;
	}
};
int main()
{
	TopLevel obj;
	return 0;
}

解析:理解这个程序需要对含有虚基类的构造顺序有比较深刻的认识。
TopLevel直接继承了Level1,虚继承了类Level2,然后这两个类又直接继承了类Base2,虚继承了类Base1,因此最后类TopLevel虚继承了类Base1和类Level2

由虚基类首先进行构造可知,我们首先运行的是类Base1的构造函数
【输出class Base1!
然后运行类Level2的构造函数,发现虚基类Base1已经构造,则构造直接继承的类Base2
【输出class Base2!
【输出class Level2!
再依次运行非虚基类,即类Level1的构造函数
【输出class Base2!
【输出class Level1!
最后运行TopLevel的构造函数
【输出class TopLevel!

运行结果:
在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值