四个函数都是C++类中的隐藏函数,析构是类结束时所调用,在一个类的创建销毁过程中***最多***执行一次(也有可能不执行,主函数的结束会导致类占用的空间直接被释放)。
析构函数
~类名(void)
{
}
析构函数
析构函数没有返回值也不需要参数,因此析构函数也不可以重载
与构造函数正好相反
先释放自身的资源
再调用成员的析构函数
最后调用父类的析构函数
如果一个类没实现析构函数,编译器会自动生成一个具有析构函数功能的二进制指令,这就是缺省析构。它负责释放编译器能够看得到的资源(成员变量、类成员、父类成员)
注意:缺省析构无法释放动态资源(堆内存)
如果一个类没有动态资源,也不需要做善后工作,缺省析构就完全够用了
构造函数
类名()
{
}
1、构造函数可以被重载(函数的多个版本)
、缺省构造,编译器自动生成的一个什么都不做的构造函数(唯一的作用就是避免编译错误)。
注意:当类中实现一个有参造时,缺省构造就不会再自动生成,如果有需要,必须显式地写出来。
3、无参构造未必无参,当给有参构造的所有参数设置默认形参,调用这种构造函数就不需要传参。
注意:所谓的"编译器生成的某某函数"其实不是真正语法意义上的函数,而是功能意义的函数,编译器作为可执行指令的生成者,它会直接生成具有某项功能的二进制指令,不需要借助高级语言语义上的函数完成此任务。
注意:如果一个类A是其他类B成员变量,那么一定要保证它有一个无参构造函数,当B的构造函数执行时会先执行成员变量的无参构造,而此时类B是无法给类A的成员变量提供参数
4、单参构造与类型转换
如果构造函数的参数只有一个,那么Test t = n语句就不会出错,它会自动调用单参构造来达到类型转换的效果
如需要禁止则加explicit
5、初始化列表
为类型成员初始化用
构造函数(参数):成员(参数)
通过初始化列表可以给类成员变量传递参数,以此调用类成员的有参构造
初始化列表也可以给 const 成员、引用成员进行初始化
成员的初始化顺序与初始化列表没有关系,而是与在类中的定义顺序有关
C++中的 const 与 C语言的 const
拷贝构造
拷贝构造又称为复制构造,是一种特殊的构造函数,它是使用一个现有的对象来构造一个新的对象,只有一个引用型的参数(对象本身)
类名(类&)
{
}
拷贝构造的参数应该加 const 保护,但编译器并没有强行限制。
编译器会自动生成一个拷贝构造函数,它负责把旧对象中的所有数据拷贝给新创建的对象
深拷贝与浅拷贝:
如果类成员中有指针,浅拷贝值拷贝指针变量的值,而深拷贝是拷贝指针变量所指向的目标
什么情况需要拷贝构造
当类成员中有指针成员,此时默认的拷贝构造(浅拷贝)就无法完成任务了,需要自己动手实现拷贝构造(深拷贝。
什么情况下会调用拷贝构造
1、使用一个旧对象给新对象赋值时
User user1 = user;
2、使用对象当做函数的参数,当调用函数时就会一起调用
赋值构造
当一个旧类对象给另一个旧类对象赋值时,就会调用赋值构造
void operator (类&)
{
}
编译器会生成一个缺省的赋值构造,它负责把一个对象的内存拷贝给另一个对象
什么情况需要实现赋值构造
当需要深拷贝时需要自己动手实现赋值构造,也就是拷贝构造与赋值构造需要同时实现
编译器会自动生成四个成员函数:构造、析构、赋值、拷贝
拷贝构造与赋值构造建议
1、缺省的拷贝构造、赋值构造函数不光会拷贝本类的数据,也会调用成员对象类对象和父类的拷贝构造和赋值构造,而不是单纯的按字节复制,因此尽量少用指针成员。
2、在函数参数中尽量使用类指针或引用来当参数(不要直接使用类对象),减少调用拷贝构造和赋值构造的机会,也可以降低数据传递的开销。
3、如果由于特殊原因无法实现完整的拷贝构造和赋值构造,建议将它们私有化,防止误用。
4、一旦为一个类实现了拷贝构造,那么也一定要实现赋值构造。