C++:类和对象(2)
1. 类的默认成员函数:类的默认成员函数就是用户没有显示实现,编译器会主动生成的成员函数称为默认成员函数。一个类,我们不写的情况下编译器会默认生成6个默认成员函数(构造函数,析构函数,拷贝构造函数,赋值重载函数,取地址重载(平凡对象,const引用对象)),最背面两个取地址重载不紧张,轻微相识一下即可。其次就是C++11以后还会增长两个默认成员函数,移动构造和移动赋值。默认长远函数很紧张,我们从两个方面去学习:
[*]第一:我们默认写时,编译器默认生成的函数行为是什么,是否满足我们的需求。
[*]第二:黏一起默认生成的函数不符合我们的需求,我们需自己实现,如何实现?
2. 构造函数
构造函数是特殊的成员函数,须要注意的是,构造函数虽名称叫构造,但是构造函数的主要任务并不是开空间创造对象,而是对象实例化时初始化对象。构造函数的本质是为了替代我们之前写的Stack 和 Date 类中的 Init 函数功能,构造函数主动调用的特点完美的替代了 Init 函数。
构造函数特点:
[*]函数名与类名雷同
[*]无返回值
[*]对象实例化系统会主动调用对应的构造函数
[*]构造函数可以重载
[*]如果类中没有显示界说构造函数,则C++编译器会主动生成一个无参的默认构造函数,一旦用户显示实现界说编译器将不再生成
[*]无参构造函数、全缺省构造函数、我们不写编译器默认生成的构造函数,都叫做默认构造函数。但是三个函数有且只有一个能有效存在,不能同时存在。无参构造函数和全缺省构造函数固然构成函数重载,但是调用时会存在歧义。要注意许多同砚会认为默认构造函数函数是编译器默认生成呢个叫默认构造,实际上无参构造函数,全缺省构造函数也是默认构造,总结一下就是不传实参就可以调用的构造就叫默认构造。
[*]我们不写,编译器默认生成的构造,对内置类型成员变量的初始化没有要求,也就是说是否初始化是不确定的,看编译器,对于自界说类型成员变量,要求调用调用这个成员变量的默认构造函数初始化。如果这个成员变量的默认构造函数初始化。如果这个成员变量,没有默认构造函数。那么就会报错,我们要初始化这个成员变量,须要用初始化列表才能解决,我们下个章节再讲。
注:C++把类型分为内置类型(基本类型)和自界说类型,内置类型就是语言提供的原生数据类型,如:Int/char/double/指针等,自界说类型就是我们使用 class/struct等关键字自界说的类型。
https://i-blog.csdnimg.cn/direct/2bda102ddcbf464aa6a7806bc3019ef7.png
https://i-blog.csdnimg.cn/direct/a6f36bd3eba84836a984397c7013ef83.png
3. 析构函数
析构函数与构造函数功能相反,析构函数不是完成对对象本身的烧毁,比如局部对象是存在栈帧,函数栈帧烧毁, 他就释放了,不须要我们管C++规定在对象烧毁时主动调用析构函数,完成对象中资源的清理释放工作。析构函数的功能类比我们之前 Stack 实现的 Destroy 功能,而像 Date 没 有 Destroy 其实就是没有资源释放,严格来说 Date 是不须要析构函数的。
析构函数的特点:
[*]析构函数的函数名是在类名前加上符号 ‘~’
[*]无参数无返回值(这里跟构造函数类似,也不须要加 void )
[*]一个类只能有一个析构函数,若显示未界说,编译器会主动生成默认的析构函数
[*]对象生命周期竣事后,系统会主动调用析构函数
[*]跟构造函数类似,我们不写编译器主动生成的析构函数对内置类型成员不做处理,自定类型成员会调用它的析构函数
[*]我们显示写析构函数,对自界说类型成员也会调用它的析构,也就是说自界说类型成员无论什么情况都会调用析构函数
[*]如果类中没有生成资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,如 Date ;如果默认生成的就可以用,也就不须要显示写析构,如MyQueue;但是有资源申请时,一定要自己写析构,否则会造成内存泄漏,如Stack。
[*]一个局部域的多个对象,C++规定后界说的先析构
https://i-blog.csdnimg.cn/direct/76636dbc030042e1b65942fb5334a256.png
4. 拷贝构造函数
如果构造函数的参数是第一个类型的引用,且任何额外的参数都有默认值,则此构造函数也叫做拷贝构造函数,也就是说拷贝构造函数是一个特殊的构造函数。
拷贝构造的特点:
[*]拷贝构造函数是一个构造函数的重载
[*]拷贝构造函数的第一个参数必须是类类型对象的引用,使用传值方式编译器直接报错,由于语法逻辑上会引发无穷递归调用。拷贝构造函数也可以多个参数但是第一个参数必须是类类型对象的引用,背面的参数必须有缺省值
[*]C++类型规定自界说类型的拷贝必须要调用拷贝构造,以是这里自界说类型传值传参和传值返回都必须调用拷贝构造完成
[*]若未显示界说拷贝构造,编译器会主动生成拷贝构造函数。主动生成的的拷贝构造对内置类型的成员变量会完成值拷贝/浅拷贝(一个字节一个字节的拷贝),对自界说类型的成员变量会调用它的拷贝构造。
[*]像 Date 如许的类成员变量满是内置类型且没有指向什么资源,编译器主动生成的拷贝构造就可以完成我们须要的拷贝,以是不须要我们显示实现拷贝构造。像 Stack 如许的类,固然也都是内置类型,但是_a指向了资源(也就是开发了内存),编译器主动生成的浅拷贝/值拷贝不符合我们的需求,以是须要我们自己实现深拷贝(对指向的资源也举行拷贝)。这里有一个小技巧,如果一个类显示实现了析构并释放资源,那么他就要显示写拷贝构造,否则就不须要。
[*]传值返回会创建一个临时对象调用拷贝构造,传值引用返回返回的是引用对象的别名(引用),没有产生拷贝。但是如果返回的对象是一个当前函数局部域的局部对象,函数竣事就烧毁了,那么使用引用返回是有问题的,这时的引用相当于野引用,类似于野指针一样。传引用返回可以减少拷贝,但是一定要确保返回对象,在当前函数竣事后还在,才能引用返回。
https://i-blog.csdnimg.cn/direct/e10a143d56924106a1e672e17a887a89.png
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]