Bootstrap

C++对象的构造和析构(构造函数和析构函数)

一.构造

1.构造的作用
看如下代码:

class text {
private:
	int x, y;
public:
	void set_xy(int x, int y) {
		this->x = x;
		this->y = y;
	}
};
int main(int argc, char** argv) {
	text t1;
	//如果没有构造函数,在这两句之间t1可能会被其他线程调用,产生不安全现象。
	t1.set_xy(1, 2);
}

因此,构造作用:在对象被创造的时候,用来初始化,防止不安全。
2.构造的定义
构造函数没返回值。
看如下代码:

class Text {
private:
	int x, y;
	
public:
//构造函数,其函数名与类名相同,没有返回值。
//方法一:
	Text(int x, int y) {
		this->x = x;
		this->y = y;
	}
//方法二:
Text(int x, int y) :x(x),y(y){}
};
int main(int argc, char** argv) {
	//调用构造函数,可以有效防止t1被其他函数调用,产生不安全现象
	//作用:在对象被创造的时候,用来初始化
	Text t1(1,2);
}

可以看到逐语句调试:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.构造的重载
普通重载、无参构造函数

class Text {
private:
	int x, y;
public:
	Text(int x, int y) {
		this->x = x;
		this->y = y;
	}
	Text() {//重载,无参的构造函数
		x = 0;
		y = 0;
	}
	Text(int x) {//重载
		this->x = x;
		y = 0;//最好此处对y初始化,当然不初始化也可以。
	}
};
int main(int argc, char** argv) {
	Text t2;//调用无参的构造函数,注意不是Text t2();
}

二.析构

析构函数没有返回值。
析构函数没有形参。
在一个对象临死之前,自动调用析构函数。
析构函数调用的顺序,跟析构函数相反,谁先构造,谁后析构。

class Text {
private:
	int x, y;
public:
	//构造函数,没有返回值
	Text(int x, int y) {
		this->x = x;
		this->y = y;
	}
	//析构函数,没有返回值;没有形参;在一个对象临死之前,自动调用析构函数;
	~Text() {
		cout << "x=" << x << ",y=" << y << endl;
	}
};
int main(int argc, char** argv) {
	Text t2(1,2);
}

结果:
可以看到这里没有调用析构函数。但是还是输出cout中内容。
在这里插入图片描述

三.默认的构造函数和析构函数

class Text {
private:
	int x, y;
public:
//以下注释,为默认构造函数和析构函数。在不写时,系统默认如下。
	/*Text() {

	}
	~Text() {

	}*/
	void get_xy() {
		cout << "x=" << x << ",y=" << y << endl;
	}
};
int main(int argc, char** argv) {
	Text t1;//默认的构造函数,其值当然为乱码。
	t1.get_xy();
}

四.拷贝构造函数

参数最好使用引用型
复制构造函数的参数为什么一定要用引用传递,而不能用值传递?
【解】值传递的参数在参数传递时有一个构造过程,即用实际参数的值构造形式参数,这个构造过程是由复制构造函数完成的。如果将复制构造函数的参数设计成值传递,会引起复制构造函数的递归调用。

class Text {
private:
	int x, y;
public:
	Text(int x, int y) {
		this->x = x;
		this->y = y;
	}
	~Text() {
		cout << "x=" << x << ",y=" << y << endl;
	}
	//拷贝函数,类似于构造函数。这里加const和&是为了保护原有的数据不被改变。
	Text(const Text& another) {
		cout << "调用拷贝函数" << endl;
		x = another.x;
		y = another.y;
	}
};
int main(int argc, char** argv) {
	Text t1(0,1);
	Text t2(t1);//拷贝函数,将t1值赋给t2。
}

结果:
在这里插入图片描述
注意:调用拷贝函数是在初始化时候调用,如果用t2=t1,则是使用赋值操作函数。

五.类中默认函数的隐藏条件

1.类中会有个默认的无参构造函数:
当没有任何显示的构造函数(显示的无参构造、显示有参构造、显示拷贝构造)的时候,默认无参构造就无法使用。

例子:如下代码有拷贝函数,看报错。

class Text {
private:
	int x, y;
public:
	//拷贝函数
	Text(const Text& another) {
		cout << "调用拷贝函数" << endl;
		x = another.x;
		y = another.y;
	}
};
int main(int argc, char** argv) {
	Text t1;
}

错误:
在这里插入图片描述
2.会有默认的拷贝函数。
3.会有默认的析构函数。

;