“生而不同”之构造函数 构造函数的作用 在创建一个新的对象时,自动调用的函数,用来进行“初始化”工作: 对这个对象内部的数据成员进行初始化。
构造函数的特点 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 使用方法: 不能主动调用。 对象销毁时,自动调用。 如果不定义,编译器会自动生成一个析构函数(什么也不做)
