类和对象(中)(一)

🌟🌟hello,各位读者大大们你们好呀🌟🌟
🚀🚀系列专栏:【C++的学习】
📝📝本篇内容: 析构函数;构造函数;拷贝构造函数
⬆⬆⬆⬆上一篇:gdb的使用
💖💖作者简介:轩情吖,请多多指教(> •̀֊•́ ) ̖́-

1.类的6个默认成员函数

如果一个类中什么成员都没有,简称为空类。
空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。
默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。
在这里插入图片描述

2.构造函数

2.1概念

在这里插入图片描述
在我们每次使用类或者以前使用结构体时都要进行初始化,经常容易忘记,然后造成bug,因此C++引入了构造函数。
构造函数是一个特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象。

2.1构造函数特性

其特性如下:
①函数名与类名相同
②无返回值
③对象实例化时编译器自动调用对应的构造函数
④构造函数可以重载
构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有一个合适的初始化值,并在对象整个生命周期内只调用一次
在这里插入图片描述
在这里插入图片描述
注意:如果通过无参构造函数创建时,对象后面不跟括号,否则就成了函数声明
在这里插入图片描述
⑤如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参数的默认构造函数,一旦用户显式编译器将不再生成
在这里插入图片描述
也就是说这样子编译器就会默认生成一个构造函数
在这里插入图片描述
但是你会惊奇的发现,对象居然没有初始化!!!???
这是为什么呢?所以说在这个地方要小心,不能说编译器会默认生成,我们就可以不写了
⑥C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如:int,char,自定义类型就是就是我们使用的是class,struct,union等自己定义的类型
⑦默认生成构造函数:

内置类型不做处理 自定义类型的成员,会去调用它的默认构造函数(不用传参数的构造函数)
无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数,全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数

这里一定要分辨清楚并熟记,不可能混淆,不然会懵的。
它在一定的场景下非常有用
在这里插入图片描述
大家看这个代码,在quene这个类里面并没有自己创建构造函数
在这里插入图片描述
大家可以通过调试,使用逐语句(F11),你会发现他会进入到Date里面的构造函数,而且调用了两次,分别是对象q的成员变量d1和d2调用的。看上图的监视,this指针和q对象的成员变量d2的值一样,这也就证明了默认生成的构造函数的特性
⑧注意:C++11中针对内置类型的成员不初始化的缺陷,又打了补丁,即内置类型成员变量在类中声明时可以给默认值
在这里插入图片描述

3.析构函数

3.1概念

析构函数:与函数构造功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

3.2析构函数的特性

析构函数是特殊的成员函数,其特性如下:
①析构函数名是在类名前加上字符~
②无参数无返回值类型
③一个类只能有一个析构函数。如果未显示定义,系统会自动调用生成默认的析构函数。注意析构函数不能重载
在这里插入图片描述
上图就是析构函数的写法
在这里插入图片描述
大家可以尝试调试,你会发现在逐语句调试下,当你到达return 0;,它会转入析构函数
在这里插入图片描述
然后对象中的资源清理完成了
④对象生命周期结束时,C++编译系统自动调用析构函数
⑤默认生成析构函数和构造函数一样,对自定义类型成员,会调用它的析构函数

在这里插入图片描述
在这里插入图片描述
和刚才一样的道理,会调用两次Date里的析构函数,不过这里这里要注意一点,那就是d2先调用析构函数,因为进入函数,创建栈帧,创建一个变量,就会像数据结构中的栈一样,在栈顶插入数据,出数据也是后进的数据先出(先进后出)。
⑥那我们什么时候需要真正用到析构函数呢?
如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,有资源申请时,一定要写,否则会造成资源泄露。

3.拷贝构造函数

3.1概念

拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型创建新对象时由编译器自动调用

3.2拷贝构造函数的特性

拷贝构造函数也是特殊的成员函数,其特征如下:
①拷贝构造函数是构造函数的一个重载形式
②拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器会直接报错,因为会引发无穷递归调用
在这里插入图片描述
可以看到用传值方式报错了
在这里插入图片描述
这样就没问题了
为什么??
其实要明白这个,就要先明白一点那就是:在传值传参的时候,内置类型,编译器可以直接拷贝,而自定义类型的拷贝,需要调用拷贝构造函数
因此在传参的时候也会调用拷贝构造函数,此时就造成了
在这里插入图片描述
那有同学就会问了,为什么内置类型可以,而自定义类型却需要调用拷贝构造函数呢
在这里插入图片描述
那就是上面这种情况,当对象里面的内容有指针指向一块空间,那你拷贝给另一个对象后,他也指向这一块空间,也就意味着,你拷贝的对象进行操作也会改变原对象的内容,而且当我程序走到最后的时候,把拷贝的对象释放了,也就意味着原对象也被释放了,当我在使用原对象的时候再释放,就会程序崩溃,因为不能释放两次。所以说我们的编译器不敢擅自主张,但是我们的内置类型不一样,当你传递的时候,你的行为,并不会影响到原对象。
况且如果你传递的是自定义类型,像Date这样的类型,你的行为也不会改变原对象,所以说编译器就没有办法来做决定了,因此不管你是哪个,全部由程序员在拷贝构造函数中设计,编译器不做处理,其中上面的需要开辟释放空间的就要用到深拷贝,而Date需要的是浅拷贝,具体是哪个,看你需求,你自己设计。
③如果未显式定义,编译器会生成默认的拷贝构造函数。默认的拷贝构造函数对对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝
注意:在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定义类型是调用其拷贝构造函数完成拷贝的
在这里插入图片描述
依旧拿我们的quene对象来举例
在这里插入图片描述
可以看到监视,确实调用了Date的拷贝构造函数
在这里插入图片描述
内置类型确实使用了浅拷贝
注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝函数一定要写的,否则就是浅拷贝。总结就是自己实现了析构函数释放空间,就需要实现拷贝构造。
④为了提高程序效率,一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用尽量使用引用。
⑤拷贝构造函数典型调用场景:
使用已存在对象创建新对象
函数参数类型为类类型对象
函数返回值类型为类类型对象

🌸🌸类和对象(中)(一)的知识大概就讲到这里啦,博主后续会继续更新更多C++的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力!💪💪

  • 18
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

轩情吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值