“生而不同”之构造函数
构造函数的作用
在创建一个新的对象时,自动调用的函数,用来进行“初始化”工作:
对这个对象内部的数据成员进行初始化。
构造函数的特点
1)自动调用(在创建新对象时,自动调用)
2)构造函数的函数名,和类名相同
3)构造函数没有返回类型
4)可以有多个构造函数(即函数重载形式)
构造函数的种类
默认构造函数
自定义的构造函数
拷贝构造函数
赋值构造函数
默认构造函数
没有参数的构造函数,称为默认构造函数。
1.合成的默认构造函数
构造函数的函数名,和类名必须相同
但没有手动定义默认构造函数时,编译器自动为这个类定义一个构造函数。
1)如果数据成员使用了“类内初始值”,就使用这个值来初始化数据成员。【C++11】
2)否则,就使用默认初始化(实际上,不做任何初始化)
注意:
只要手动定义了任何一个构造函数,编译器就不会生成“合成的默认构造函数”
一般情况下,都应该定义自己的构造函数,不要使用“合成的默认构造函数”
【仅当数据成员全部使用了“类内初始值”,才宜使用“合成的默认构造函数”】
2.手动定义的默认构造函数
说明:如果某数据成员使用类内初始值,同时又在构造函数中进行了初始化,
那么以构造函数中的初始化为准。
相当于构造函数中的初始化,会覆盖对应的类内初始值。
自定义的重载构造函数
构造函数的函数名,和类名必须相同,且里面有参数
创建对象时进行传参
拷贝构造函数
1.手动定义的拷贝构造函数
假设在Human定义一个拷贝构造函数
访问权限必须为public
public:
Human(const Human&);
2.合成的拷贝构造函数
说明:
合成的拷贝构造函数的缺点: 使用“浅拷贝”
解决方案:在自定义的拷贝构造函数中,使用‘深拷贝
(例如类里面有个属性 char * name,进行浅拷贝时只是对值进行了拷贝,此时两个对象的指针name共同指向一块内存地址,进行深拷贝时为该对象开辟另一个空间,使指针name指向另一个地址)
什么时候调用拷贝构造函数
1.调用函数时,实参是对象,形参不是引用类型
如果函数的形参是引用类型,就不会调用拷贝构造函数
2.函数的返回类型是类,而且不是引用类型
3.对象数组的初始化列表中,使用对象
赋值构造函数
有以Human类为例
赋值构造函数定义:Human& Human::operator=(const Human &man);
如果没有定义赋值构造函数,编译器会自动定义“合成的赋值构造函数”,
与其他合成的构造函数,是“浅拷贝”(又称为“位拷贝”)。
使用时注意一下浅拷贝问题
h1 和 h2分别为Human对象
h2 = h1; //调用赋值构造函数
“最后的晚餐”之析构函数
作用:
对象销毁前,做清理工作。
具体的清理工作,一般和构造函数对应
比如:如果在构造函数中,使用new分配了内存,就需在析构函数中用delete释放。
如果构造函数中没有在堆空间申请资源(主要是内存资源),
那么很少使用析构函数。
函数名:
~类型
没有返回值,没有参数,最多只能有一个析构函数
访问权限:
一般都使用public
使用方法:
不能主动调用。
对象销毁时,自动调用。
如果不定义,编译器会自动生成一个析构函数(什么也不做)