【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函数。

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

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

相关文章

通过css设置filter 属性,使整个页面呈现灰度效果,让整个网页变灰

通过css设置filter 属性设置页面整体置灰 效果图: 通过设置 filter 属性为 grayscale(100%)&#xff0c;页面中的所有元素都会被应用灰色滤镜效果&#xff0c;使整个页面呈现灰度效果。 <style type"text/css"> html { filter: grayscale(100%); -webkit-f…

《Linux从练气到飞升》No.15 Linux 环境变量

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的…

C++函数模板和类模板

C另一种编程思想称为泛型编程&#xff0c;主要利用的技术是模板 C提供两种模板机制&#xff1a;函数模板和类模板 C提供了模板(template)编程的概念。所谓模板&#xff0c;实际上是建立一个通用函数或类&#xff0c; 其类内部的类型和函数的形参类型不具体指定&#xff0c; 用…

SpringBoot代理访问本地静态资源400 404

SpringBoot代理访问静态资源400 404 背景&#xff1a;pdf文件上传到linux服务器上&#xff0c;使用SpringBoot代理访问问题&#xff1a;访问过程中可能会出现400、404问题 前提&#xff1a;保证有文件&#xff0c;并且文件路径正确 SpringBoot如何配置静态资源代理&#xff0…

网络综合布线实训室建设方案

一、网络综合布线系统概述 网络综合布线系统是为了满足数据通信需求而设计和建立的一套基础设施。它提供了数据传输、信号传输和电力供应的基础结构&#xff0c;支持各种网络设备和终端设备之间的连接。 网络综合布线系统通常包括以下组成部分&#xff1a; 1&#xff09; 数据…

1.MySQL数据库的基本操作

数据库操作过程&#xff1a; 1.用户在客户端输入 SQL 2.客户端会把 SQL 通过网络发送给服务器 3.服务器执行这个 SQL,把结果返回给客户端 4.客户端收到结果,显示到界面上 数据库的操作 这里的数据库不是代表一个软件&#xff0c;而是代表一个数据集合。 显示当前的数据库 …

PHP基础

PHP&#xff08;外文名:PHP:Hypertext Preprocessor&#xff0c;中文名&#xff1a;“超文本预处理器”&#xff09;是一种免费开源的、创建动态交互性站点的强有力的服务器端脚本语言 <h1>My Name is LiSi!</h1> <script>console.log("This message is…

GuLi商城-前端基础Vue-使用Vue脚手架进行模块化开发

自己亲自实践&#xff1a; mac安装webpack webpack 简介Webpack 是一个非常流行的前端构建工具&#xff0c;它可以将多个模块&#xff08;包括CSS、JavaScript、图片等&#xff09;打包成一个或多个静态资源文件&#xff08;bundle&#xff09;&#xff0c;以便用于部署到生产…

测试人进阶技能:单元测试报告应用指南

为什么需要单元测试 从产品角度而言&#xff0c;常规的功能测试、系统测试都是站在产品局部或全局功能进行测试&#xff0c;能够很好地与用户的需要相结合&#xff0c;但是缺乏了对产品研发细节&#xff08;特别是代码细节的理解&#xff09;。 从测试人员角度而言&#xff0…

无涯教程-TensorFlow - TensorBoard可视化

TensorFlow包含一个可视化工具&#xff0c;称为TensorBoard&#xff0c;它用于分析数据流图&#xff0c;还用于了解机器学习模型。 TensorBoard的重要功能包括查看有关垂直对齐的任何图形的参数和详细信息的不同类型统计的视图。 深度神经网络包括多达36&#xff0c;000个节点…

Java实现CAS的原理

文章目录 1、 什么是CAS2、CAS的原理3、CAS的应用场景4、Java中的CAS实现5、使用AtomicInteger实现线程安全的计数器6、CAS实现原子操作的三大问题6.1、ABA问题6.2、循环时间长6.3、只能保证一个共享变量的原子性 7、总结 1、 什么是CAS CAS&#xff08;Compare and Swap&…

读书笔记-《ON JAVA 中文版》-摘要22[第二十章 泛型-1]

文章目录 第二十章 泛型1. 简单泛型1.1 简单泛型1.2 一个元组类库 2. 泛型接口3. 泛型方法3.1 泛型方法3.2 变长参数和泛型方法 4. 构建复杂模型 第二十章 泛型 普通的类和方法只能使用特定的类型&#xff1a;基本数据类型或类类型。如果编写的代码需要应用于多种类型&#xff…

5G+AI数字化智能工厂建设解决方案PPT

导读&#xff1a;原文《5GAI数字化智能工厂建设解决方案》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。数字化智能工厂定义 智能基础架构协同框架 - 端、边、云、网…

ARM 作业1

一、思维导图 二、 1. 2. .text 文本段 .globl _start 声明_start:mov r0,#0mov r1,#0fun:cmp r1,#100bhi stopadd r0,r0,r1add r1,r1,#1b fun stop:b stop .end

【3Ds Max】车削命令的简单使用(以制作花瓶为例)

简介 在3ds Max中&#xff0c;"车削"&#xff08;Lathe&#xff09;是一种建模命令&#xff0c;用于创建围绕轴线旋转的几何形状。通过车削命令&#xff0c;您可以将一个闭合的平面或曲线几何形状旋转&#xff0c;从而生成一个立体对象。这种方法常用于创建圆柱体、…

原生微信小程序自定义picker多列选择器:picker写法用法

前言: 最近用原生微信小程序写法写医疗相关项目微信小程序&#xff0c;在编辑个人资料的时候&#xff0c;需要很多选择器&#xff0c;比如城市地区选择器&#xff0c;职业职称选择器&#xff0c;科室选择器&#xff0c;学校选择器&#xff0c;学历选择器&#xff0c;年份日期选…

YOLOv5改进系列(21)——替换主干网络之RepViT(清华 ICCV 2023|最新开源移动端ViT)

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制 YOLOv5改进系列(2

基于YOLOv8模型的五类动物目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要&#xff1a;基于YOLOv8模型的五类动物目标检测系统可用于日常生活中检测与定位动物目标&#xff08;狼、鹿、猪、兔和浣熊&#xff09;&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与…

如何区分闰年与平年

首先要明白 地球绕太阳运行周期为365天5小时48分46秒&#xff08;合365.24219天&#xff09;&#xff0c;即一回归年&#xff08;tropical year&#xff09;。公历的平年只有365日&#xff0c;比回归年短约0.2422 日&#xff0c;每四年累积约一天&#xff0c;把这一天加于2月末…

CentOS7源码安装MySQL详细教程

&#x1f60a; 作者&#xff1a; Eric &#x1f496; 主页&#xff1a; https://blog.csdn.net/weixin_47316183?typeblog &#x1f389; 主题&#xff1a;CentOS7源码安装MySQL详细教程 ⏱️ 创作时间&#xff1a; 2023年08月014日 文章目录 1、安装的四种方式2、源码安装…