【C++笔记】C++之类与对象(中)

【C++笔记】C++之类与对象(中)

  • 1、类的构造函数
    • 1.1、构造函数的基本用法
    • 1.2、构造函数的7个特性
  • 2、类的析构函数
    • 2.1、析构函数的基本用法
    • 2.2、析构函数的6个特性
  • 3、类的拷贝构造函数
    • 3.1、拷贝构造的基本用法
    • 3.2、拷贝构造的“无限套娃”陷阱
    • 3.3、深拷贝与浅拷贝
  • 4、运算符重载
    • 4.1、运算符重载的基本使用方法
    • 4.2、运算符重载使用的注意事项
    • 4.3、重载前置++和后置++怎么区分?
  • 5、类的const成员函数

1、类的构造函数

其实每个类都有6个默认成员函数:
在这里插入图片描述
默认成员函数指的是:用户没有显示实现编译器会自动生成的函数。
这些函数主要完成一些初始化和资源回收和复制的工作,而且有些有些是会自动调用的。有了这些成员函数,我们的类使用起来就能更省心。
而我们这个阶段只会接触到前两个“初始化和清理”和“拷贝构造”。

第一个默认成员函数就是构造函数,它主要完成的是对类的初始化工作。

1.1、构造函数的基本用法

其实构造函数,就和我们以前写的初始化函数一样,只不过构造函数更方便一些,在写法上他有两个特征:
在这里插入图片描述
然后函数体内的写法就和以前的初始化函数差不多。
就拿栈这个类来举例,我们就可以这样来写构造函数:
在这里插入图片描述
当然了,构造函数也是可以传参的,我们可以传一个参数表示要开多少空间:
在这里插入图片描述
而它的用法就是在创建类对象的时候,在类对象后面加一个括号,括号后面加上对应的参数即可:
在这里插入图片描述
而构造函数是自动调用的,为了验证这个特点,我们可以把构造函数改成无参的:
在这里插入图片描述

1.2、构造函数的7个特性

其实构造函数,难就难在特性太多了,不好记,构造函数总的有7个特性,前面是个是:

  1. 函数名与类名相同。
  2. 无返回值。
  3. 对象实例化时编译器自动调用对应的构造函数。
  4. 构造函数可以重载。

前三个我们已经验证过了,我们就从第4个开始逐一验证。

4. 构造函数可以重载。

既然C++搞出了函数重载,那为什么构造函数就不能重重载呢?而且构造函数的重载为我们提供了更多的初始化方法,例如对于栈这个类,我们就可以写这样的两个构造函数,这样在初始化的时候就可以有两种初始化的方式可以选择了:
在这里插入图片描述

5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。

验证个这个特性我们就只需要保留一个有参数的构造函数,再使用不传参初始化的方式即可:
在这里插入图片描述
而要是我们不主动去写构造函数,编译器就不会报错了:
在这里插入图片描述

6.编译器生成的默认构造函数对内置类型不进行处理,对自定义类型就调用其默认构造函数。

我们可以通过调试来看一看上面的例子中的,个成员有没有被处理:
在这里插入图片描述
我们可以看到,所有的成员都还只是随机值,因为这里的所有成员都是内置类型的。

我们可以再随便定义一个自定义类型,来验证第二点:
在这里插入图片描述

7. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为
是默认构造函数。

构造函数麻烦就麻烦在这里,我们大概率都会认为编译器自动生成的无参的构造函数就是默认构造函数,但是它偏不是,而是有三个。

而我们只需要证明全缺省的构造函数是默认构造函数即可:
在这里插入图片描述
其实构造函数可以简单理解为,不用传参就可以调用的函数,所以全缺省的构造函数也是一个默认构造函数。

但要是我们不提供默认构造函数,而只是写了一个不符合默认构造函数的构造函数,如果我们在初始化的时候以不传参的方式初始化,编译器就会报错,因为找不到默认构造函数:
在这里插入图片描述
这是因为一旦我们显示的写了构造函数,那不管其满不满足默认构造函数的条件,编译器都不会在生成默认的构造函数了。

2、类的析构函数

析构函数其实就类似于我们以前写的销毁函数destroy,它的主要工作就是,清理数据和释放空间。

2.1、析构函数的基本用法

析构函数在语法上有两个特点:
在这里插入图片描述
还是拿栈来举例,栈的析构函数可以这样写:
在这里插入图片描述
注意:析构函数不能显示调用!

2.2、析构函数的6个特性

与构造函数一样,析构函数也有一些让人头晕的特性,前面两个:
在这里插入图片描述
我们已经清楚。

那我们从第三个开始说起。

3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载

也就是说析构函数不能重载:
在这里插入图片描述
至于编译器自动生成的析构函数,我不会验证,反正记住就行了。

4. 对象生命周期结束时,C++编译系统系统自动调用析构函数

这一条上面已经验证过了。

5.编译器自动生成的析构函数对于内置类型不作处理,对于自定义类型则去调用其析构函数。

置于为什么对于内置类型不作处理,我想应该很容易理解,因为内置类型本身出了作用域就会随着内存一并被回收,所以处不处理都一样了。

而关于第二点,我们可以用以下例子来证明:
在这里插入图片描述

  1. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如
    Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。

3、类的拷贝构造函数

就像内置类型总是需要将一个变量的数据拷贝给另一个变量一样,自定义类型也需要将一个对象的数据拷贝给另个一对象,这就需要我们的拷贝构造了。

3.1、拷贝构造的基本用法

拷贝构造其实是构造函数的一个重载样式,所以它的函数名也是也类名相同,并且拷贝构造规定只有一个参数,就是一个同类型的引用。
就拿日期类来举例,日期类的拷贝构造就可以这样写:
在这里插入图片描述
然后调用其实也是向初始化一样,只不过参数变成了另一个对象:
在这里插入图片描述

3.2、拷贝构造的“无限套娃”陷阱

为什么拷贝构造一定要传一个对象的引用,那直接穿一个对象行不行呢?
其实,C++规定,如果函数传参传的是一个类对象,那么在函数调用的第一步传参的时候,就要去调用这个类的拷贝构造去生成一个拷贝。
我们可以通过以下例子来验证:
在这里插入图片描述
我们可以看到,这里只是简单地调用了一下func(),而函数内并没有做任何操作,却已经调用了拷贝构造。从而我们就可以确认类的传值传参就回去调用拷贝构造。

这样我们就可就可以来解释为什么,拷贝构造规定只能传对象的引用了,如果我们拷贝构造传是对象的值拷贝,那么在调用拷贝构造之前就会先去调用拷贝构造,而调用拷贝构造就需要传值,那就会再去调用拷贝构造,如此循环往复无穷无尽。所以如果拷贝构造传的是类对象的只拷贝就会陷入这样的一一个死循环:
在这里插入图片描述
而我这里的编译器是进行了强制检查的。

3.3、深拷贝与浅拷贝

其他的构造函数都有编译器自动生成的版本,拷贝构造也有,但编译器自动生成的拷贝构造完成的是“浅拷贝”,而浅拷贝存在一些问题,这个问题我们可以通过下面这个例子看出:
在这里插入图片描述
可以看出,对于栈这个类只进行浅拷贝的话就崩了。而且我们看到调用了两次析构函数。
这是因为:

编译器自动生成的拷贝构造对内置类型会进行值拷贝,而对于自定义类型会去调用其拷贝构造。

而现在写的栈的所有成员都是内置类型,那就是只进行值拷贝了,这里的问题出就出在析构函数。因为成员函数都只进行了值拷贝,所以两个栈对象的_data都指向了同一块空间。而而当其中一个栈析构了以后,这一块空间就已经被释放了,然后后一个栈又调用了一次析构函数,这就会导致同一块空间被释放了两次,这就是报错的原因。

所以对于栈这种有额外空间申请的类,我们应该进行的是“深拷贝”:
在这里插入图片描述

4、运算符重载

有时候我们也需要将各个类对象进行比较,但我们不能直接运用运算符进行比较,因为只有内置类型才能这样做。因为编译器并不知道你自己定义的类型到底该怎样比较。
这就需要运算符重载出场了。

4.1、运算符重载的基本使用方法

运算符重载的函数名就是“operator”加上各种运算符,而返回值可以是布尔类型或其他各个类型。
比如我们要比较两个日期类对对象那个更小,就可以这样写:
在这里插入图片描述
这样我们就可以直接使用小于运算符比较两个类对象了:
在这里插入图片描述
而这里之所以要加上括号的原因是,流插入的优先级要高于小于运算符,如果不加上的话就会报错了:
在这里插入图片描述

4.2、运算符重载使用的注意事项

运算符重载的使用也有一些注意事项。

1.不能通过连接其他符号来创建新的操作符:比如operator@

当然,我们不能自己创造运算符,我们重载的运算符必须是C++已有的运算符,例如:
在这里插入图片描述

2.重载操作符必须有一个同类类型参数

这个必须有的同类型参数就是我们的this,因为对象调用的时候一定要将自己的指针传过去,只不过这个this指针是隐藏起来的。

剩下的三点分别是:

3.用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
4.作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
5.".* :: sizeof ?: . "注意以上5个运算符不能重载。这个经常在笔试选择题中出现。

4.3、重载前置++和后置++怎么区分?

对于函数名相同且,不用传参数的运算符重载的函数,我们该怎么区分呢?
例如这里的前置++和后置++。
我们可以为其中一个添加一个额外的“无用”的参数:
在这里插入图片描述
这样便一起在调用的时候就可以看情况,是否要加上一个参数来区分了。
当然,这个参数你传任何值都是一样的,因为它的存在只是为了做一个区分,本身不是用来使用的。.

5、类的const成员函数

因为在引用的过程中,权限不能放大,所以对于const对象有些函数是不能调用的:
在这里插入图片描述
因为引用的底层其实就是用指针实现的,所以这里可以将引用等同于指针。因为Print隐藏的this指针不是const的,所以这里的调用实则是将const的指针转化成了非const指针,涉及到了权限的放大。
为了决绝这个问题,我们可以添加一个const修饰的Print函数:
在这里插入图片描述
const函数的语法就是在函数的后面加上一个const。
这里的const和非const的函数其实是构成了重载。
这样便一起在调用的时候就会自动去匹配最符合的函数,const的对象就去调用const的Print函数,非const对象就会去调用非const的Print函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/98521.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二叉树搜索

✅<1>主页&#xff1a;我的代码爱吃辣&#x1f4c3;<2>知识讲解&#xff1a;数据结构——二叉搜索树☂️<3>开发环境 &#xff1a;Visual Studio 2022&#x1f4ac;<4>前言&#xff1a;在之前的我们已经学过了普通二叉树&#xff0c;了解了基本的二叉树…

vue导出文件流获取附件名称并下载(在response.headers里解析filename导出)

导出文件流下载&#xff0c;拦截器统一处理配置 需求以往实现的方法&#xff08;各自的业务层写方法&#xff09;现在实现的方法&#xff08;axios里拦截器统一配置处理&#xff09;把文章链接复制粘贴给后端&#xff0c;让大佬自己赏阅。 需求 之前实现的导出都是各自的业务层…

springboot之多数据源配置

文章目录 一、多数据源的典型使用场景1 业务复杂&#xff08;数据量大&#xff09;2 读写分离 二、如何实现多数据源通过AbstractRoutingDataSource动态指定数据源多数据源切换方式AOPMyBatis插件 三、spring集成多个Mybatis框架 实现多数据源控制四、dynamic-datasource 多数据…

01.Django入门

1.创建项目 1.1基于终端创建Django项目 打开终端进入文件路径&#xff08;打算将项目放在哪个目录&#xff0c;就进入哪个目录&#xff09; E:\learning\python\Django 执行命令创建项目 F:\Anaconda3\envs\pythonWeb\Scripts\django-admin.exe&#xff08;Django-admin.exe所…

残差网络实现

代码中涉及的图片实验数据下载地址&#xff1a;https://download.csdn.net/download/m0_37567738/88235543?spm1001.2014.3001.5501 代码&#xff1a; import torch import torch.nn as nn import torch.nn.functional as F #from utils import load_data,get_accur,train i…

茂名 湛江阳江某学校 ibm x3850服务器维修经历

简介&#xff1a;中国广东省阳江市某中学联想 IBM System x3850 x6服务器维修 io板故障处理经历分享&#xff1a; 这一天一位阳江的老师经其他学校老师介绍推荐对接我&#xff0c;说他们学校有一台ibm服务器出问题了&#xff0c;老师大致跟我描述了一下这台服务器发生故障的前…

Android12之com.android.media.swcodec无法生成apex问题(一百六十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

Apache DolphinScheduler 支持使用 OceanBase 作为元数据库啦!

DolphinScheduler是一个开源的分布式任务调度系统&#xff0c;拥有分布式架构、多任务类型、可视化操作、分布式调度和高可用等特性&#xff0c;适用于大规模分布式任务调度的场景。目前DolphinScheduler支持的元数据库有Mysql、PostgreSQL、H2&#xff0c;如果在业务中需要更好…

iOS UIAlertController控件

ios 9 以后 UIAlertController取代UIAlertView和UIActionSheet UIAlertControllerStyleAlert和UIAlertControllerStyleActionSheet。 在UIAlertController中添加按钮和关联输入框 UIAlertAction共有三种类型&#xff0c;默认&#xff08;UIAlertActionStyleDefault&#xff0…

【Linux】进程信号篇Ⅰ:信号的产生(signal、kill、raise、abort、alarm)、信号的保存(core dump)

文章目录 一、 signal 函数&#xff1a;用户自定义捕捉信号二、信号的产生1. 通过中断按键产生信号2. 调用系统函数向进程发信号2.1 kill 函数&#xff1a;给任意进程发送任意信号2.2 raise 函数&#xff1a;给调用进程发送任意信号2.3 abort 函数&#xff1a;给调用进程发送 6…

机器学习深度学习——NLP实战(情感分析模型——数据集)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——BERT&#xff08;来自transformer的双向编码器表示&#xff09; &#x1f4da;订阅专栏&#xff1a;机器…

Kubernetes 安全机制 认证 授权 准入控制

客户端应用若想发送请求到 apiserver 操作管理K8S资源对象&#xff0c;需要先通过三关安全验证 认证&#xff08;Authentication&#xff09;鉴权&#xff08;Authorization&#xff09;准入控制&#xff08;Admission Control&#xff09; Kubernetes 作为一个分布式集群的管理…

Flink的Standalone部署实战

在Flink是通用的框架&#xff0c;以混合和匹配的方式支持部署不同场景&#xff0c;而Standalone单机部署方便快速部署&#xff0c;记录本地部署过程&#xff0c;方便备查。 环境要求 1&#xff09;JDK1.8及以上 2&#xff09;flink-1.14.3 3&#xff09;CentOS7 Flink相关信…

ELK日志监控系统搭建docker版

目录 日志来源elk介绍elasticsearch介绍logstash介绍kibana介绍 部署elasticsearch拉取镜像&#xff1a;docker pull elasticsearch:7.17.9修改配置⽂件&#xff1a;/usr/share/elasticsearch/config/elasticsearch.yml启动容器设置密码&#xff08;123456&#xff09;忘记密码…

opencv-进阶05 手写数字识别原理及示例

前面我们仅仅取了两个特征维度进行说明。在实际应用中&#xff0c;可能存在着更多特征维度需要计算。 下面以手写数字识别为例进行简单的介绍。 假设我们要让程序识别图 20-2 中上方的数字&#xff08;当然&#xff0c;你一眼就知道是“8”&#xff0c;但是现在要让计算机识别…

【JUC系列-01】深入理解JMM内存模型的底层实现原理

一&#xff0c;深入理解JMM内存模型 1&#xff0c;什么是可见性 在谈jmm的内存模型之前&#xff0c;先了解一下并发并发编程的三大特性&#xff0c;分别是&#xff1a;可见性&#xff0c;原子性&#xff0c;有序性。可见性指的就是当一个线程修改某个变量的值之后&#xff0c…

自动化测试用例设计实例

在编写用例之间&#xff0c;笔者再次强调几点编写自动化测试用例的原则&#xff1a; 1、一个脚本是一个完整的场景&#xff0c;从用户登陆操作到用户退出系统关闭浏览器。 2、一个脚本脚本只验证一个功能点&#xff0c;不要试图用户登陆系统后把所有的功能都进行验证再退出系统…

智慧水利利用4G物联网技术实现远程监测、控制、管理

智慧水利工业路由器是集合数据采集、实时监控、远程管理的4G物联网通讯设备&#xff0c;能够让传统水利系统实现智能化的实时监控和远程管理。工业路由器利用4G无线网络技术&#xff0c;能够实时传输数据和终端信息&#xff0c;为水利系统的运维提供有效的支持。 智慧水利系统是…

湘潭大学 湘大 XTU OJ 1055 整数分类 题解(非常详细)

链接 整数分类 题目 Description 按照下面方法对整数x进行分类&#xff1a;如果x是一个个位数&#xff0c;则x属于x类&#xff1b;否则将x的各位上的数码累加&#xff0c;得到一个新的x&#xff0c;依次迭代&#xff0c;可以得到x的所属类。比如说24&#xff0c;246&#…

手写模拟SpringBoot核心流程(二):实现Tomcat和Jetty的切换

实现Tomcat和Jetty的切换 前言 上一篇文章我们聊到&#xff0c;SpringBoot中内置了web服务器&#xff0c;包括Tomcat、Jetty&#xff0c;并且实现了SpringBoot启动Tomcat的流程。 那么SpringBoot怎样自动切换成Jetty服务器呢&#xff1f; 接下来我们继续学习如何实现Tomcat…