类和对象(2)——距离C++又近了一步

目录

一、构造函数

1.1声明和定义构造函数

1.2成员名和参数名

1.3构造函数的使用

1.4初始化列表

二、析构函数

2.1析构函数的概念

2.2析构函数的性质

三、拷贝构造函数

四、赋值运算符重载

4.1运算符重载

4.2赋值运算符重载


一、构造函数

我们知道,C++中类的数据部分的访问状态是私有的,这就意味着程序不能直接访问数据成员,而只能通过成员函数来访问数据成员。为了让创建的实例化对象一开始都有一个合适的初始值(如果需要额外调用函数赋初值未免太过麻烦),C++提供了一个特殊的成员函数——类构造函数,C++提供了函数的名称和语法,而程序员需要提供方法定义。名称和类名相同。

构造函数是一个特殊的成员函数名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。

1.1声明和定义构造函数

已知我们的构造函数名和类名相同,现在我们来定义一个Date类的构造函数:

1.2成员名和参数名

如果我们不熟悉构造函数,我们可能会试图将类成员名称用作构造函数的参数名,如下所示:
其实这样是不对的。构造函数的参数表示的不是类成员,而是赋给类成员的值。因此,二者不能相同,否则代码就会出现上图的情况,如"year = year",虽然系统会默认传一个 this 指针,但是我们也应该避免这种混淆,以下给出两种解决方案:

我比较不听从他们的建议,我选择了在数据成员中使用 _ 前缀,其实大家也可以按照自己的喜好随意命名,这里只是提供一种思路。

1.3构造函数的使用

这里有两种使用构造函数的语法,而且提供了一个错误案例:

d3的报错也说明了系统不允许创建未初始化的对象,但是当我们没有人为提供构造函数时,系统会自动生成默认构造函数,无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个:

注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为
是默认构造函数
此时我们也可以调用 Print() 查看系统的默认构造函数:另外,C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在​​​​​​​类中声明时可以给默认值(但这只能成为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值):

1.4初始化列表

除了上述的声明和定义构造函数,还有一种初始化方式就是初始化列表,初始化列表是指以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。

为什么学习完之前的构造函数还要再学这种呢?这并非画蛇添足,而是在一些情境下,必须使用初始化列表,下面列出几种情况:
1.引用成员变量
2.const成员变量
3.自定义类型成员(且该类没有默认构造函数时)

下面我们来介绍一下初始化列表的一些性质:
1.初始化列表有一个走后门之处:不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化,如果没有,再进入函数体内部寻找。
2.成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关

二、析构函数

2.1析构函数的概念

学指针时,我们创建一个指针后还要把它销毁,那我们能创建一个对象,如何销毁一个对象呢?
析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

2.2析构函数的性质

析构函数是特殊的成员函数,其特征如下:
1. 析构函数名是在类名前加上字符 ~。
2. 无参数无返回值类型。析构函数必须是 ~类名()
3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载。
4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

我们在这里创建的Date类的析构函数不承担任何重要的工作,因此可以将它编写为不执行任何操作的函数,当然,为了我们能明显地看出析构函数何时被调用,可以这样编写代码:
另外,我们还要知道的是,越早创建的对象,析构函数的调用越靠后:

最后,我们想谈的就是不同区域的函数最终按什么顺序完成析构?
局部对象(先定义后析构)-> 静态区域 -> 全局对象(先定义后析构)

三、拷贝构造函数

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

拷贝构造函数可以说是构造函数的重载形式,所以它的语法和构造函数类似:

和前面学过的两个函数类似,拷贝构造函数若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数是传值拷贝,也就是浅拷贝
注意:类中如果没有涉及资源申请时,拷贝构造函数是否自定义都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的,否则就是浅拷贝。

四、赋值运算符重载

4.1运算符重载

运算符重载是C++多态的一种体现。运算符重载将重载的概念扩展到运算符上,允许赋予C++运算符多种含义,实际上,我们已经见过很多运算符重载的例子。如 * ,在指针运用上,它充当解引用的作用,而在两数相乘时,它有充当乘法的作用。

C++运算符重载语法如下:
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)

1.如果我们要定义运算符重载,可能要访问类内private数据,此时我们可以直接将其定义为类的成员函数。
注意:这里的函数参数默认已经有了this指针,我们输入的_year其实是this->_year
           所以我们只需要再传入我们需要比较的另一个参数即可
2.如果我们要把函数定义在类外,那么我们要提前用到后面会学的友元函数(简单来说,被friend关键字修饰的函数可以访问类内的私有成员)/

4.2赋值运算符重载

我们想要类似拷贝构造函数一样的运算符重载,应该怎么办呢?下面假设我们的类 class Type

首先,我们要明确函数返回值类型应该是Type&,如下图:
然后我们现在先设计一个大概,有了之前this指针的经验,我们轻松就可以在类内设计出来: 
现在我们看一下还缺点什么?返回值!那么应该返回什么呢?环顾了四周,怎么什么都不能返回啊?非也非也,不要忘记了this指针!我们传参的时候可是默认传了个this指针呢!这个指针是谁?不就是我们要被赋值的对象吗?但要注意,我们返回的应该是解引用的this。
光说了类内,但是类外呢?我们运算符重载时可是学了两种方法啊,我记得在类外是用友元吧,那现在呢?赋值运算符重载在类外怎么实现呢?
当我们像运算符重载一样使用友元后:
哎呦呵,我才刚在类内声明呢,我类外还没实现呢,您怎么就给我报错了?
报错原因显而易见,下面我们来探讨一下为什么赋值运算符只能是成员函数呢。
答:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数。
而其他的如值拷贝的内容、什么时候必须手写赋值运算符重载,就和拷贝构造函数的内容一致了,大家自行查阅:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python:练习:输出int值a占b的百分之几。例如:输入1和4,输出:25%。

案例: 输出int值a占b的百分之几。例如:输入1和4,输出:25%。 思考: 所有的一步步思考,最后综合起来。 首先,确定 输出,那么就用input,而且是int值,所以肯定…

用vivado创建一个赛灵思AXI的IP核

一、新建一个管理IP的任务 二、设置板子,verilog语言和文件位置 三、创建新的IP核 添加一个axi-full的master接口和axi-full的slave接口 四、查看赛灵思AXI代码 第一个是axi的master接口代码,下面的是axi的slave接口代码 五、打包IP核以供后续使用 六、…

请求响应与统一响应结果

1.请求响应 1.安装postman 2.简单的参数 //原始的请求参数的方法RequestMapping("/simoleParam")public String simpleParam(HttpServletRequest request){String name request.getParameter("name");String ageStr request.getParameter("age&quo…

逻辑电路集成块手册

还在查找74XX集成块的数据手册吗,还在找逻辑门电路的手册吗 不用找了,直接打开此电子书,查找就可以了,内部框图,真值表引脚序号都有DOWNLOAD:https://www.ti.com/lit/pdf/scyd013?keyMatchLOGIC%20POCKET%20DATA%20BOOK 失效直接上TI官方网站搜索logic pocket data book即可搜…

【web APIs】5、(学习笔记)有案例!

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、js组成window对象定时器-延迟函数location对象navigator对象histroy对象 二 、本地存储(今日重点)localStorage(重点&am…

FLask会话技术和Flask模板语言

二、FLask会话技术和Flask模板语言 1.会话技术 cookie 客户端的会话技术:让服务器认识浏览器,常用于登录 cookie本身由浏览器保存,通过Response将cookie写到浏览器上,下一次访问,浏览器会根据不同的规则携带cookie过…

【leetcode】链表分割

大家好,我是苏貝,本篇博客带大家刷题,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️ 目录 方法1. 不用哨兵位方法2. 用哨兵位 点击查看题目 思路: 将链表分为2个链表list1和list2,…

Cookie、Session和JWT

摘要:Cookie、Session和JWT都不是什么新的技术了,最近用到了就比较和总结下。 我们知道http协议是无状态的,用户登录后如何验证和保存用户状态呢?下面来介绍 1. 使用Cookie和Session验证登录状态 session是保存在服务端的一种数…

【中科院计算所】WSDM 2024冠军方案:基于大模型进行多文档问答

作者:李一鸣 张兆 中科院计算所 会话式多文档问答旨在根据检索到的文档以及上下文对话来回答特定问题。 在本文中,我们介绍了 WSDM Cup 2024 中“对话式多文档 QA”挑战赛的获胜方法,该方法利用了大型语言模型 (LLM) 卓越的自然语言理解和生…

项目解决方案: 实时视频拼接方案介绍

目 录 1、实时视频拼接概述 2、适用场景 3、系统介绍 3.1拼接形式 3.1.1横向拼接 3.1.2纵向拼接 3.2前端选择 3.2.1前端类型 3.2.2推荐配置 3.3后端选择 3.3.1录像回放 3.3.2客户端展示 4、拼接方案介绍 4.1基于4K摄像机的拼接方案 4.1.1系统架构…

安秉源代码加密,不仅可以正常加密,对编译调试无任何影响

源代码防泄密对于很多企业来讲都在使用,特别是在广东一些做智能制造的企业,这些企业在很早就意识到源代码防泄密的重要性,很多企业采用加密的方式对企业的源代码进行加密,也采用了相对应的加密软件,但是在使用一些加密…

Javaweb之SpringBootWeb案例之 SpringBoot原理的详细解析

3. SpringBoot原理 SpringBoot使我们能够集中精力地去关注业务功能的开发,而不用过多地关注框架本身的配置使用。而我们前面所讲解的都是面向应用层面的技术,接下来我们开始学习SpringBoot的原理,这部分内容偏向于底层的原理分析。 在剖析Sp…

P沟道与N沟道MOSFET的基本概念

N沟道与P沟道MOSFET基本原理与区别 学习MOSFET时的简单笔记作为个人总结,仅供学习参考,实际电路设计请直接略过!!! 文章目录 N沟道与P沟道MOSFET基本原理与区别前言一、MOSFET ?二、N沟道MOS管原理三、P沟…

老卫带你学---leetcode刷题(130. 被围绕的区域)

130. 被围绕的区域 问题 给你一个 m x n 的矩阵 board ,由若干字符 ‘X’ 和 ‘O’ ,找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。 示例 1: 输入:board [[“X”,“X”,“X”,“X”]…

mitmproxy安装与配置

文章目录 一、mitmproxy的安装二、运行mitmproxy1、配置客户端代理方式一,设置全局代理方式二,设置浏览器代理 2、客户端安装mitmproxy提供的CA证书手工安装步骤:自动安装步骤: mitmproxy是一个免费的开源交互式的HTTPS代理工具。…

放着奥威-用友BI方案不用?糊涂!

放着奥威-用友BI方案不用,自己在那死磕数据可视化报表开发、数据分析报表开发,白白投了大量的人力物力进去,还得不到好效果,比百忙一场还要亏。 奥威-用友BI方案究竟有多优秀? 1、分析快,报表制作快 半个…

嵌入式驱动学习第一周——git的使用

前言 本文主要介绍git的使用,包括介绍git,gitee,以及使用gitee创建仓库并托管代码 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程,未来预计四个月将高强度更新本专栏,喜欢的可以关注本博主并订阅本专栏&#xf…

1.1 编程环境的安装

汇编语言 汇编语言环境部署 第二个运行程序直接双击安装一直下一步即可MASM文件复制到D盘路径下找到dosbox安装路径:C:\Program Files (x86)\DOSBox-0.74找到该文件双击打开它,修改一下窗口大小 把这两行改成如下所示 运行dos,黑框中输入mou…

Dockerfile(4) - RUN 指令详解

RUN 运行命令 shell 形式 命令在 shell 中运行Linux 上默认为 /bin/sh -cWindows 上 cmd /S /C RUN <command> exec 形式 RUN ["executable", "param1", "param2"] 必须双引号&#xff0c;不能是单引号 两种写法的实际栗子 RUN …

MYSQL02高级_目录结构、默认数据库、表文件、系统独立表空间

文章目录 ①. MySQL目录结构②. 查看默认数据库③. MYSQL5.7和8表文件③. 系统、独立表空间 ①. MySQL目录结构 ①. 如何查看关联mysql目录 [rootmysql8 ~]# find / -name mysql /var/lib/mysql /var/lib/mysql/mysql /etc/selinux/targeted/tmp/modules/100/mysql /etc/seli…