当前位置: 首页 > news >正文

【C++】类与对象理解和学习(中)

专栏放在【C++知识总结】,会持续更新,期待支持🌹


六大默认成员函数

前言

每个类中都含有六大默认成员函数,也就是说,即使这个类是个空类,里面什么都没有写,但是编译器依然会自动生成六个默认成员函数,可以说它们六个是祖师爷钦点的“天选之子”。如下图所示:

这里我们来谈一谈何为默认?默认是有两种情况:

  1. 我们不写,编译器自动生成的

  1. 我们根据规定写的(后面会一一讲到),但是函数参数为全缺省或者不含有函数参数的。

构造函数

首先来谈谈它的作用,就是减少我们手动初始化,实现自动初始化。就比如下面的代码,我们要想对对象进行初始化,就要调用函数Init,会很麻烦,而构造函数就是为了解决这个麻烦的。接下来我们先谈一谈它的创建规则

构造函数的函数名与类名相同
无返回值
对象实例化时编译器自动调用对应的构造函数。
构造函数可以重载(可以存在多个构造函数,但默认构造函数只有一个)

(当然现阶段初始化的方式本质实际上是通过函数体赋值实现,并不是完全意义上的初始化,后面的章节会讲到初始化列表,通过初始化列表实现真正意义上的初始化)

这里还有一个注意点需要注意一但自己写了构造函数,不管是默认构造函数,还是普通构造函数,编译器都不会自动默认生成构造函数。


class Date
{
public:普通构造函数Date(char a){_year = 2023;_month = 2;_day = 19;}
//一但我们自己写了构造函数,不管是属于默认类型的还是普通类型的,编译器都不会自动默认生成
private:int _year;int _month;int _day;
};
int main()
{//Date d1;//这里编译器会报错,没有合适的默认构造函数,这是因为我们自己写了普通类型的构造函数,编译器就不会再自动生成默认构造函数,而我们的类中又没有写默认构造函数,所以会报错。return 0;
}

默认构造函数

上面我们已经讲过默认构造函数的形式,一种是编译器自动生成,另一种是自己根据规则来写但是函数无参数或者参数为全缺省参数。后面的自己写的我们上面讲过了,这里我们来谈一谈编译器自动默认生成的。

我们发现编译器自动生成的默认构造函数竟然没有给我们的数据做初始化处理,这是为啥呢?实际上是我们的祖师爷埋下的一个大坑:默认构造函数对内置类型(int double char...)不做处理,但是对自定义类型(struct class union)会自动调用它所对应的默认构造函数。我们下面来实验一下会发现确实如此:

不过对于这个大坑,C++11中新增了一个补丁(一些老版本的编译器可能不支持)可以在声明时给内置类型一个缺省值:如下

(当然对于构造函数还会有一些比较恶心的地方,我们把它放在后面一章来讲解关于初始化列表相关知识及注意点)

析构函数

析构函数的作用就是对类对象中的资源进行清理,它的创建方式与构造函数大致相同

析构函数名是在类名前加上字符 ~。
无参数无返回值类型。
一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载(只能存在一个,要么是编译器自动生成的,要么是自己写的)
对象生命周期结束时,C++编译系统系统自动调用析构函数

当然,在析构函数这里也存在着一个大坑,与默认构造函数相同,由于析构函数不支持重载,所以我们写的实际上就是默认析构函数,它在清理资源时对内置类型不做处理,对自定义类型会调用该自定义类型的默认析构函数。

因此我们可以这样来说:

对于普通的内置类型,我们不需要写析构函数(写了后我们自己的就是默认析构函数),编译器自动生成的就够用了,但是对于向系统申请空间,涉及到动态内存开辟的,则必须由我们自己写析构函数进行释放资源,不然会造成内存泄漏。

构造与析构的调用顺序

这里简单提一嘴,就是类对象默认构造与默认析构函数的调用顺序与我们学过的一种数据结构——栈类似,先定义的先调用构造,后调用析构(先进后出)

Date d1;
Date d2;
//构造函数调用顺序:d1 d2
//析构函数调用顺序:d2 d1

拷贝构造函数

拷贝构造函数看名字也可以看出来,是属于构造函数的一种重载。作用是完成拷贝工作。它的创造规则如下:

与构造函数相同
这里需要注意的是拷贝构造函数只有一个参数,并且这个参数必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
如果自己没写,编译器会生成默认的拷贝构造,拷贝方式为浅拷贝(值拷贝),对内置类型实现浅拷贝,对自定义类型则调用该自定义类型的拷贝构造函数。

谈一谈无穷递归问题

对于自定义类型,在传值传参的时候会·产生拷贝构造,而调用拷贝构造函数又需要传参,传值传参又会产生拷贝构造...(无限套娃)

正确写法应为传引用传参

    Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}

谈一谈深浅拷贝

所谓浅拷贝,其实就是值拷贝一个字节一个字节的完成拷贝,我们的编译器默认生成的就是浅拷贝。所以对于两个上面这种日期类对象,假如实现将d1拷贝给d2,我们可以这么来写:

Date d2(d1);//或者:Date d2=d1;

当然,由于编译器生成的默认拷贝构造既然已经可以实现一个字节一个字节拷贝,也就是浅拷贝(值拷贝),那么对于这种日期类对象,我们可以不写拷贝构造函数,因为编译器自动生成的已经够用了,我们把代码屏蔽,依然可以编译通过,实现拷贝。

那么可能有人会很好奇,既然编译器生成的已经够用了,那么还需要我们自己来写嘛?答案是肯定的,就比如以下这种情况:涉及到空间资源开辟

因此,我们可以这么说:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的,否则浅拷贝会出大问题。

(另外给大家一个小建议:一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用

尽量使用引用,这样做是为了减少拷贝,提高程序运行效率)。

赋值运算符重载

运算符重载

C++为了增强代码的可读性引入了运算符重载所谓运算符重载的用处是什么呢?实际上就是是我们的自定义类型也可以直接使用操作符进行操作。就比如说,整型a大于整型b,我们可以直接用>进行判断,但是对于自定义类型来说,这里就不能直接使用>。

那么什么是运算符重载呢?实际上运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名为:关键字operator后面接需要重载的运算符符号

函数原型:返回值类型 operator操作符(参数列表)

这里还有以下几点需要注意:

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

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

  1. 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义

  1. 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this

  1. .* :: sizeof ?: . 注意以上5个运算符不能重载。

我们再来谈一谈赋值运算符重载

赋值运算符重载是属于运算符重载中的一种,我们需要注意以下几点:

参数类型:const T&,传递引用可以提高传参效率

返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值

另外,我们不要与拷贝构造记混了,拷贝构造是给实例化对象初始化,此时实例化对象还没有创建完成,但赋值是两个都已经实例化后的对象,a的值赋值给b,b=a,此时a与b都是以及实例化后的。
这里我们还需要注意的就是,它是祖师爷钦点的天选之子之一,所以即使我们不写,编译器也会生成一个默认赋值运算符重载,但是,我们写的话只能在类内写,不可以写在全局,这是因为如果类中没有赋值运算符,编译器会自动生成一个,假如此时我们在类外又写了一个,就会发生冲突!

关于默认运算符重载

编译器生成的默认运算符重载,对于内置类型会以值的方式逐字节拷贝(即浅拷贝),对于自定义类型,则会调用该自定义类型的默认运算符重载。(因此,我们上面的这个日期类,我们不写赋值运算符重载,用编译器生成的就够用了)

(当然,与我们上面讲的默认拷贝构造一样,如果不涉及到向内存申请空间资源,我们就不需要写,但是一旦涉及到,我们就需要使用深拷贝的方式来实现,原因与拷贝构造那里讲的一样

const成员函数

const成员函数其实就是在成员函数后面加个const,这里的const修饰的是隐含形参:this指针!const放在成员函数后面后,*this即调用这个函数的类对象里的数据便不可以发生修改!

取地址及const取地址操作符重载

这两个我们一般不需要进行重载,用编译器生成的默认的即可(自己返回一个假地址玩一玩的话,也可以自己写着玩)


end

生活原本沉闷,但跑起来就会有风!🌹

相关文章:

【C++】类与对象理解和学习(中)

专栏放在【C知识总结】,会持续更新,期待支持🌹六大默认成员函数前言每个类中都含有六大默认成员函数,也就是说,即使这个类是个空类,里面什么都没有写,但是编译器依然会自动生成六个默认成员函数…...

每日英语学习(11)大英复习单词和翻译

2023.2.20 单词 1.contemplate 思考、沉思 2.spark 激起 3.venture 冒险 4.stunning 极好的 5.dictate 影响 6.diplomatic 外交的 7.vicious 恶性的 8.premier 首要的 9.endeavor 努力 10.bypass 绕过 11.handicaps 不利因素 12.vulnerable 脆弱的 13.temperament 气质、性格…...

x79主板M.2无法识别固态硬盘

问题描述: 这几天在装电脑,买了块M.2接口固态硬盘。装上去始终无法读取到硬盘,一开始以为是寨板Bios问题不支持M.2的设备。更新了最新的BIOS然后还是没有识别出来,然而将日常用的电脑PM510硬盘装上发现可以识别,而且日常用电脑也…...

配置Tomcat性能优化

配置Tomcat性能优化 📒博客主页: 微笑的段嘉许博客主页 💻微信公众号:微笑的段嘉许 🎉欢迎关注🔎点赞👍收藏⭐留言📝 📌本文由微笑的段嘉许原创! &#x1f4…...

Hive3 安装方式详解,datagrid自定义驱动连接hive

1 Hive的安装方式 hive的安装一共有三种方式:内嵌模式、本地模式、远程模式。 元数据服务(metastore)作用是:客户端连接metastore服务,metastore再去连接MySQL数据库来存取元数据。有了metastore服务,就可以有多个客户端同时连接…...

约束优化:约束优化的三种序列无约束优化方法(罚函数法)

文章目录约束优化:约束优化的三种序列无约束优化方法(罚函数法)外点罚函数法L2-罚函数法:非精确算法对于等式约束对于不等式约束L1-罚函数法:精确算法内点罚函数法:障碍函数法参考文献约束优化:…...

你真的会做APP UI自动化测试吗?我敢打赌百分之九十的人都不知道这个思路

目录 前言 一,开发语言选择 二,UI测试框架选择 1,Appium 2,Airtest 3,选择框架 三,单元测试框架选择 四,测试环境搭建 1,测试电脑选择 2,测试手机选择 3&#…...

GIT:【基础三】Git工作核心原理

目录 一、Git本地四个工作区域 二、Git提交文件流程 一、Git本地四个工作区域 工作目录(Working Directory):电脑上存放开发代码的地方。暂存区(Stage/Index):用于l临时存放改动的文件,本质上只是一个文件,保存即将提交到文件列…...

【1.12 golang中的指针】

1. 指针 区别于C/C中的指针,Go语言中的指针不能进行偏移和运算,是安全指针。 要搞明白Go语言中的指针需要先知道3个概念:指针地址、指针类型和指针取值。 1.1. Go语言中的指针 Go语言中的函数传参都是值拷贝,当我们想要修改某…...

十五.程序环境和预处理

文章目录一.程序翻译环境和执行环境1.ANSI C 标准2.程序的翻译环境和执行环境二.程序编译和链接1.翻译环境2.编译本身的几个阶段3.运行环境三.预处理1.预定义符号2.#define(1)#define定义标识符(2)#define定义宏(3&…...

高并发系统设计之负载均衡

本文已收录至Github,推荐阅读 👉 Java随想录 文章目录DNS负载均衡Nginx负载均衡负载均衡算法负载均衡配置超时配置被动健康检查与主动健康检查LVS/F5Nginx当我们的应用单实例不能支撑用户请求时,此时就需要扩容,从一台服务器扩容到…...

嵌入式Linux从入门到精通之第十四节:Linux IO控制技术

目录 设备控制概述 操作设备文件函数 监听文件描述符 示例 设备控制概述 对于硬件设备,Linux采用了与裸机完全不同的机制进行管理。 Linux下的所有硬件(IO、键盘、鼠标等)均是以文件的形式进行统一管理的,每个设备在/dev/目录下都有一个设备文件与之对应。操作相应的文件…...

/etc/fstab文件

文件/etc/fstab存放的是系统中的文件系统信息,当系统启动的时候,系统会自动地从这个文件读取信息,并且会自动将此文件中指定的文件系统挂载到指定的目录。当正确的设置了该文件,则可以通过mount /directoryname命令来加载一个文件…...

深度学习神经网络基础知识(一) 模型选择、欠拟合和过拟合

专栏:神经网络复现目录 深度学习神经网络基础知识(一) 本文讲述神经网络基础知识,具体细节讲述前向传播,反向传播和计算图,同时讲解神经网络优化方法:权重衰减,Dropout等方法,最后进行Kaggle实…...

同样做软件测试,为什么有人月入3k-5k,有人能拿到17-20k?

同样做软件测试,为什么有人月入3k-5k,有人能拿到17-20k? 虽然各大培训机构一直鼓吹软件测试行业薪资高,但是依旧有一些拿着3-5k薪资,甚至找不到软件测试工作的人。 先来看一些例子: 小A在一家培训机构学完…...

如何运行YOLOv5的代码,实现目标识别

YOLOv5和v8都由Ultralytics这家创业公司开发的https://github.com/ultralytics/yolov5环境配置git clone https://github.com/ultralytics/yolov5.git作者要求python3.6(我用的3.8也能跑通)torch1.7.0pip install -r requirements_my_version.txtrequire…...

【正点原子FPGA连载】第十四章SD卡读写TXT文本实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id692450874670 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html 第十四章SD卡读写…...

【人工智能AI :Open AI】我想写一本书,书名是《中国文学史》,帮我列一下目录,细化到三级目录,不少于2000字。

我想写一本书,书名是《中国文学史》,帮我列一下目录,细化到三级目录,不少于2000字。 中国文学史 第一章 经典文学 1.1 先秦文学 1.1.1 先秦诗歌 1.1.1.1 小雅 1.1.1.2 大雅 1.1.1.3 颂 1.1…...

「文档数据库之争」MongoDB和CouchDB的比较

MongoDB和CouchDB都是基于文档的NoSQL数据库类型。文档数据库又称mdocument store,通常用于存储半结构化数据的文档格式及其详细描述。它允许创建和更新程序,而不需要引用主模式。移动应用程序中的内容管理和数据处理是可以应用文档存储的两个字段。Mong…...

c++11 标准模板(STL)(std::unordered_set)(三)

定义于头文件 <unordered_set> template< class Key, class Hash std::hash<Key>, class KeyEqual std::equal_to<Key>, class Allocator std::allocator<Key> > class unordered_set;(1)(C11 起)namespace pmr { templ…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理

在城市的某个角落&#xff0c;一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延&#xff0c;滚滚浓烟弥漫开来&#xff0c;周围群众的生命财产安全受到严重威胁。就在这千钧一发之际&#xff0c;消防救援队伍迅速行动&#xff0c;而豪越科技消防一体化安全管控平台构建的消防“…...

向量几何的二元性:叉乘模长与内积投影的深层联系

在数学与物理的空间世界中&#xff0c;向量运算构成了理解几何结构的基石。叉乘&#xff08;外积&#xff09;与点积&#xff08;内积&#xff09;作为向量代数的两大支柱&#xff0c;表面上呈现出截然不同的几何意义与代数形式&#xff0c;却在深层次上揭示了向量间相互作用的…...

【Redis】Redis从入门到实战:全面指南

Redis从入门到实战:全面指南 一、Redis简介 Redis(Remote Dictionary Server)是一个开源的、基于内存的键值存储系统,它可以用作数据库、缓存和消息代理。由Salvatore Sanfilippo于2009年开发,因其高性能、丰富的数据结构和广泛的语言支持而广受欢迎。 Redis核心特点:…...