深入理解C++类的构造函数与析构函数


在研究 C++ 类的继承、派生、组合时,一直没有清晰地了解构造函数与析构函数的调用过程。本章通过点 - 线组合类,来深入分析组合类情况下,对象的构造与析构。

1.问题的引入

源代码:
<span style="font-size:18px;">#include <iostream>
using namespace std;
#include<math.h>

class Point
{
private:
	int x;    int y;
	
public:
	int getx();
	int gety();
	Point()
	{ cout<<"Calling the default construction of Point!"<<endl; }
	Point(int xx, int yy)
	{ cout<<"Calling the parameter construction of Point!"<<endl; x = xx; y = yy;}
	Point(Point &pt)
	{ cout<<"Calling the copy construction of Point!"<<endl; x = pt.x;  y = pt.y;}
	~Point()
	{cout<<"Calling the destructor of Point!"<<endl;}
};
int Point::getx() { return x;}
int Point::gety() { return y;}
//==================================================================
class Line
{
private:
	Point dot1,dot2;
	double Len;
public:
	Line()
	{cout<<"Calling the default construction of Line!"<<endl;}
	Line(Point pt1, Point pt2)
	{
		cout<<"Calling the parameter construction of  Line"<<endl;
		dot1 = pt1;  dot2 = pt2;
		double Linex = abs( dot1.getx() - dot2.getx() );
		double Liney = abs( dot1.gety() - dot2.gety() );
		Len = sqrt( Linex*Linex + Liney*Liney);
	}
	Line(Line &l)
	{
		cout<<"Calling the copy construction of Line"<<endl;
		Len = l.Len;
	}
	~Line(){ cout<<"Calling the destructor of Line!"<<endl;}
};
void main()
{
	Point mypoint1; 
	Point mypoint2(1,2);
	Point mypoint3(mypoint2);
	cout<<mypoint2.getx()<<endl;
	cout<<mypoint3.gety()<<endl;
	Point mypt1(1,2),mypt2(3,4);
	Line line1(mypt1,mypt2);
	Line line2(line1);

}</span>
程序执行结果:


2.逐条语句进行分析 

<span style="font-size:18px;">Point mypoint1; </span>
该条语句是利用Point类进行初始化Point对象,此时,编译器会自动调用程序的构造函数。由于对象定义不带有任何参数,所以此时仅调用程序的默认构造函数。

输出为“Calling the default construction of Point!”

<span style="font-size:18px;">Point mypoint2(1,2);</span>
语句定义一个Point类的对象,但是此时我们应该注意到对mypoint2对象进行了初始化,此时操作系统会调用含有参数的构造函数

具体行为过程是,在内存中开辟空间定义临时变量 int xx, int yy;通过参数传递,xx = 1. yy = 2;然后在执行含有参数构造函数的函数体,完成临时变量值向Point类的属性x,y的赋值。

输出“Calling the parameter construction of Point!”

<span style="font-size:18px;">Point mypoint3(mypoint2);</span>

语句仍然定义了一个Point类的对象,但是应该注意到,这里利用了前一个对象mypoint2对mypoint3进行初始化 。调用了Point类复制构造函数。相当于&pt = mypoint2 。此时,通过看看内存地址,我们可以看到,编译器并没用定义一个Point类的对象临时pt。而是采用了“引用”的模式,pt仅仅是mypoint2的一个别名而已!!!

输出“Calling the copy construction of point!”


<span style="font-size:18px;">cout<<mypoint2.getx()<<endl;
cout<<mypoint3.gety()<<endl;</span>
输出当前Point类的属性x,y;输出“ 1 2”
<span style="font-size:18px;">Point mypt1(1,2),mypt2(3,4);</span>

定义Point类的两个带有初始化参数的对象,

输出“Calling the parameter construction of Point!”

"Calling the parameter construction of Point!"

Line line1(mypt1,mypt2);
注意到,此时我们在尝试利用参数传递的方式来构造Line的对象line1,也就是说,相比较而言Line是上一层的类,而mypt1/mypt2是底层类的对象。此时的程序执行过程可以分解为:

&pt = mypt2;  // “Calling the copy construction of Point!”

&pt = mypt1; // "Calling the copy construction of Point!"

//注意到,此时仍然是引用的格式,没有进行临时对象的构建

line1(mypt1,mypt2); //“Calling the parameter construction of Line!”

重点:当我们利用底层类的对象对上一层类对象进行初始化之后,要立刻销毁底层类的对象,及调用相应的析构函数。

“Calling the destructor of Point!” //销毁对象mypt1

“Calling  the destructor of Point!” //销毁对象mypt2

Line line2(line1);
参考上例,此时的拷贝过程可以分解为:

&l = line1; //引用传递

“Calling the default construction of Point!”

"Calling the default construction of Point!"

//执行Line复制构造函数的函数体

“Calling the copy construction of Line”

退出程序后,对所有对象进行销毁,其顺序为“与构造函数调用顺序相反”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值