详解运算符重载,赋值运算符重载,++运算符重载

目录

 

前言

运算符重载

概念

目的

写法

调用

注意事项

详解注意事项

运算符重载成全局性的弊端

类中隐含的this指针

赋值运算符重载

赋值运算符重载格式

注意点

明晰赋值运算符重载函数的调用

连续赋值

传引用与传值返回

默认赋值运算符重载

前置++和后置++重载


 

前言

先梳理一下本篇的脉络,首先会讲解运算符重载的概念,这是本篇的基本概念。其次会讲解赋值运算符的重载,这是本篇的重点,最后是++运算符重载,只需明晰规则即可。此外,希望这篇文章能让大家有所收获,如有不足之处,还请指正,小编会虚心接受并改进质量。


运算符重载

概念

C++引入了运算符重载。它和函数重载的概念类似,可以让一个符号有不同的功能而具体的功能是由自己实现的。

目的

是为了增强代码的可读性。C++中有这个概念。“  + ” 这个符号可以实现两个整形或浮点型相加,因为这两个类型是语言自己定义的。但它能实现两个的相加吗?显然不行,因为这个类型是自己设计的,相加要实现怎样的效果只有自己知道。

写法

运算符重载也是函数的一种,只不过函数名比较特殊,其返回值和参数列表和普通函数一样。参数的数量和操作数的数量一致,参数的顺序和操作数的顺序一致

函数名字为:关键字 operator 后面接需要重载的运算符符号
函数原型: 返回值类型 operator操作符(参数列表)
示例(判断两个日期类是否相等) 6a7426722be748c09f92f174a390438b.png

调用

分为显式调用(加关键字)和隐式调用(不加关键字),如下代码

operator==(d1, d2)//显式调用
==(d1, d2) //隐式调用

注意事项

运算符重载的注意事项
1.
不能通过连接其他符号来创建新的操作符:比如operator@
2.
重载操作符必须有一个类类型参数
3.
用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义
4.
作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
5.
.*   ::   sizeof   ?:   . 注意以上5个运算符不能重载。

详解注意事项

1.想要重载一个符号,必须复用语言定义过的符号,不能凭空捏造。如下代码就会报错。


bool operator@(const Date& d1, const Date& d2)

3edf11b21896451db0160e75394c0680.png

 

2.假如要把“  ”这个符号重载成整形和字符型的相加,这毫无意义并且会破坏语言原有的运算规则,此时编译器会强制报错。2051ff45d4364400ae069f2729d92837.png

3.如果要把加“  ”这个符号重载两个相加,那具体实现的逻辑就必须是加的逻辑,但这一点没有强制性,因为这不是语法的错误,编译器不会强行报错。需要自行规范。

4.这一点会在下面提到。

5. .*   ::   sizeof   ?:   .  这五个运算符强制不能重载,大家可能对于 .* 运算符比较陌生, .* 运算符并不是本篇章的重点,但为了大家能够记住这个运算符,小编写了一段代码并且配上了详细的注释让大家感受一下 .* 运算符的作用。提醒:对 .* 运算符不感兴趣的可以跳过,不会对后面内容的理解有任何影响

class Date //日期类
{
public:Date(int year = 1, int month = 1, int day = 1) //构造函数{_year = year;_month = month;_day = day;}void DatePrintf() //打印函数{cout << _year << _month << _day << endl;}private:int _year; //年int _month; //月int _day; //日};typedef void(Date::* DP)();  //这里是给一个函数类型取了一个别名,别名是 DP ,类型是 void ()  日期类中的打印函数也是这个类型int main()
{DP dp = &Date::DatePrintf; //把成员函数中打印函数的指针给  dp , 一般来说函数名就代表该函数的地址,但成员函数规定要加上取地址符号Date d; //实例化一个类 , 对象名为d(d .* dp)();  //调用d对象的打印函数return 0;
}

上述代码中提到了构造函数,小编专门写了一篇构造函数的文章  http://t.csdnimg.cn/vGE9A 对构造函数不是很理解的可以看一下,上述代码运行的结果是打印三个一,如下图:44a4d6a112a24bfc953ea9a38af259c2.png

运算符重载成全局性的弊端

的数据一般是私有的,运算符重载是函数的一种,而全局性的函数是不可以访问类的私有数据的。如下图:162bed8bef9f45ec907434c79ebe9831.png

难道我们要为了运算符重载要把中的数据设为共有吗,那的封装性如何保证呢?本篇给出的解决方案是把运算符重载函数定义为成员函数,意思是直接定义在类中。如下代码

class Date //日期类
{
public:Date(int year = 1, int month = 1, int day = 1) //构造函数{_year = year;_month = month;_day = day;}bool operator==(const Date& d2)  //运算符重载函数,一个参数是this ,一个是 const Date&{return _year == d2._year&& _month == d2._month && _day == d2._day;}
private:int _year; //年int _month; //月int _day; //日};

中隐含的this指针

如果把运算符重载函数定义成员函数会少定义一个参数,但并没有真的少了一个参数,有一个隐含的this指针作为了该函数的第一个参数。如下图:

374bc775a0f94e7ab78fe002f93f29a7.png

this是类型的隐含参数,如果运算符重载函数定义再了里面,这个参数就可以省去不写。



赋值运算符重载

下面的内容涉及到拷贝构造函数,对拷贝构造函数的理解比较模糊的可以参考一下小编写的详解拷贝构造一文   http://t.csdnimg.cn/CkLs5  。

赋值运算符重载格式

参数类型:类类型的引用

返回值:可传值返回,可传引用返回,传引用返回比传值返回效率要高,后面会细讲。

代码示例

Date& operator=(const Date& d) //日期类的赋值运算符的重载的定义{_year = d._year;_month = d._month;_day = d._day;}


在这里先定义一个日期类,下面讨论的知识点都会用到这个日期类,大家先看一下代码

class Date  //日期类
{
public:Date(int year = 1, int month = 1, int day = 1)  //全缺省构造函数{_year = year;_month = month;_day = day;}Date(const Date& d)  //拷贝构造函数{_year = d._year;_month = d._month;_day = d._day;}void operator=(const Date& d)  //赋值运算符重载{_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;
};

注意点

赋值运算符能再类中重载。因为赋值运算符重载函数是类的默认成员函数,如果重载成全局函数,编译器会为类自动生成默认赋值运算符重载函数,此时就会和全局的冲突。

 

明晰赋值运算符重载函数的调用

大家能分清下面的调用吗

int main()
{Date d; //实例化dDate d1(d);  //示例化d1,并把d的值拷贝给d1Date d2 = d;  //示例化d2,并把d的值拷贝给d2Date d3;  //实例化d3d3 = d;  //把d的值赋值给d3}

画图演示其调用

98ed8a8aaa514f57aff46380b58f7acb.png

连续赋值

上述代码中的赋值重载函数随是否能实现连续赋值呢?答案是不能。因为该函数只能完成赋值工作,并不会再把类的数据返回。代码改进

Date operator=(const Date& d)  //赋值运算符重载
{_year = d._year;_month = d._month;_day = d._day;return *this;  //返回被赋值的形参的数据
}

传引用与传值返回

上述代码中传的是的值,由于中封装了许多数据,想要把的数据传回去,需要调用该的拷贝构造函数,我们可以打印一下拷贝构造函数来观察一下,如下图bf4b0060ee1b41f0918bc9bf34b08702.png

调用拷贝构造函数拷贝数据的消耗是很大的,如果传引用返回能不能减少拷贝呢,如下图b9a4473eb4804945a1c8f806aa545c9b.png

结果很明确,传引用返回并没有调用拷贝构造函数,这说明传引用返回比传值返回效率更高,只要该类出了作用域不会销毁,都可以传引用返回

如果我要自己给自己赋值会怎么样呢,这是没必要的,可以再改进一下代码

Date& operator=(const Date& d)  //赋值运算符重载
{if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;
}

 

默认赋值运算符重载

用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。内置类型成员变量是直接赋值的,而自定义类型成员变量需要 调用对应类的赋值运算符重载完成赋值。
我将用如下代码为大家讲解默认运算符重载函数的浅拷贝的弊端
class Date //日期类
{
public:Date() //构造函数{_year = 1;_month = 1;_day = 1;_a = (int*)malloc(sizeof(int) * 7); //为a开辟空间for (int i = 0; i < 7; i++){_a[i] = 0;}}private:int _year; //年int _month; //月int _day;  //日int* _a;  //指向一块空间
};
int main()
{Date d; //实例化对象dDate d1; //实例化对象d1d = d1; //把对象d1的数据赋值给对象d
}

下面是代码调试示意图d5ef4d7d614849a0b8f2b73434940f9a.png

下面是逻辑示意图 d6336db5888a4122a700d3705c71ba65.png
对象d的_a不再指向原有空间,使原有空间丢失,造成内存泄漏。 如果类中未涉及到资源管理,赋值运算符是否实现都可以;一旦涉及到资源管理则必 须要实现


 

前置++和后置++重载

Date& operator++() //日期的前置++
{_day += 1;return *this;
}Date operator++(int) //日期类的后置++
{Date temp(*this);_day += 1;return temp;
}
C++规定:  前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载,后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器
自动传递。


想为大家推荐 aMereNobody 大佬写的文章   http://t.csdnimg.cn/m9uVE 

本篇的内容到此结束啦

 

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

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

相关文章

华为OD机试 - 分披萨 - 动态规划(Java 2024 C卷 200分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试…

抖去推短视频矩阵系统----源头开发

为什么一直说让企业去做短视频矩阵&#xff1f;而好处就是有更多的流量入口&#xff0c;不同平台或账号之间可以进行资源互换&#xff0c;最终目的就是获客留咨&#xff0c;提单转化。你去看一些做得大的账号&#xff0c;你会发现他们在许多大的平台上&#xff0c;都有自己的账…

HTML5 <video> 标签属性、API 方法、事件、自定义样式详解与实用示例

HTML5 <video> 标签为网页内嵌视频提供了强大且便捷的功能。以下是对 <video> 标签的主要属性、API 方法、事件、自定义样式及其使用示例的详细介绍&#xff1a; 一、属性 1. src 定义&#xff1a;指定视频文件的 URL。示例&#xff1a;<video src"my_v…

【C++杂货铺】继承

目录 &#x1f308;前言&#x1f308; &#x1f4c1; 继承的概念和定义 &#x1f4c2; 概念 &#x1f4c2; 定义 &#x1f4c1; 基类和派生类对象赋值转换 &#x1f4c1; 继承中的作用域 &#x1f4c1; 派生类的默认成员函数 构造函数 析构函数 拷贝构造函数 赋值重载…

有公网IP,如何设置端口映射实现访问?

很多中小型公司或个人会根据自身需求自建服务器&#xff0c;或者将自己内网的服务、应用发布到外网&#xff0c;实现异地访问&#xff0c;如远程桌面、网站、数据库、公司的管理系统、FTP、管家婆、监控系统等等。 没接触过的人可能会觉得这个很难&#xff0c;实际上使用快解析…

Golang插件系统实现

插件可以在解耦的基础上灵活扩展应用功能&#xff0c;本文介绍了如何基于Golang标准库实现插件功能&#xff0c;帮助我们构建更灵活可扩展的应用。原文: Plugins with Go 什么是插件 简单来说&#xff0c;插件就是可以被其他软件加载的软件&#xff0c;通常用于扩展应用程序的功…

[入门]测试层级-ApiHug准备-测试篇-005

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace 这里的测…

学习STM32第十五天

SPI外设 一、简介 STM32F4XX内部集成硬件SPI收发电路&#xff0c;可以由硬件自动执行时钟生成、数据收发等功能&#xff0c;减轻CPU负担&#xff0c;可配置8位/16位数据帧&#xff0c;高位&#xff08;最常用&#xff09;/低位先行&#xff0c;三组SPI接口&#xff0c;支持DMA…

第一篇【传奇开心果系列】我和AI面对面聊编程:深度比较PyQt5和tkinter.ttk

传奇开心果系列博文 系列博文目录我和AI面对面聊编程系列 博文目录前言一、今天我们面对广大读者选择PyQt5和tkinter.ttk做比较这个话题目的是什么&#xff1f;二、举一个最简单的pyqt5信号和插槽的例子三、这和tkinter的点击事件有什么区别&#xff1f;四、如何选择&#xff1…

MySQL Explan执行计划详解

Explan执行计划 首先我们采用explan执行计划 执行一条sql&#xff0c;发现返回了12个列&#xff0c;下面会详细解释每一列 1、ID列 id列的值是代表了select语句执行顺序&#xff0c;是和select相关联的&#xff1b;id列的值大的会优先执行&#xff0c;如果id列为空最后执行&a…

数据库的创建

数据库分类 通过查看对象资源管理器来区分数据库类型 数据库物理文件的组成 : 数据库文件 日志文件 创建一个主数据文件和一个日志文件

上线流程及操作

上节回顾 1 搜索功能-前端&#xff1a;搜索框&#xff0c;搜索结果页面-后端&#xff1a;一种类型课程-APIResponse(actual_courseres.data.get(results),free_course[],light_course[])-搜索&#xff0c;如果数据量很大&#xff0c;直接使用mysql&#xff0c;效率非常低--》E…

淘宝商品数据抓取新策略:API接口助力获取标题、分类与店铺名

随着电子商务的迅猛发展&#xff0c;淘宝作为中国最大的网络购物平台&#xff0c;其商品数据对于众多商家、研究者和市场分析师来说具有极高的价值。然而&#xff0c;如何高效、准确地抓取淘宝商品数据&#xff0c;尤其是商品标题、分类和店铺名等关键信息&#xff0c;一直是一…

nginx部署上线

1. windows配置nginx 打包命令 npm run build:prod 1. 安装 nginx mac windows 2. mac / windows 环境下ngnix部署启动项目 2. nginx 解决 history 的 404 问题 3. nginx配置代理解决生产环境跨域问题

极速、易用、高度定制化的开源社区交流平台:Flarum

Flarum&#xff1a;轻盈高效&#xff0c;引领未来社区互动新风尚的革命性论坛平台- 精选真开源&#xff0c;释放新价值。 概览 Flarum是一款精心打造的现代网站讨论平台&#xff0c;以其精炼高效而著称。作为 esoTalk 和 FluxBB 的理念和技术的集大成者&#xff0c;Flarum 致力…

Ubuntu 20.04 LTS 在3588安卓主板上测试yolov8-1.0版本的yolov8n-seg模型

0. 创建虚拟环境 #!< 创建虚拟环境yolov8 $ sudo pip install virtualenv $ sudo pip install virtualenvwrapper $ mkvirtualenv yolov8 -p /usr/bin/python3.81. 将yolov8n-seg.pt转换为yolov8n-seg.onnx文件 #!< 创建项目目录yolov8-rknn并下载yolov8n-seg.pt模型文…

虚拟机vm桥接模式linux(centos,ubuntu)联网

台式机网线 查看宿主机网络 编辑虚拟机—>虚拟网络编辑器–>更改设置 选择&#xff0c;确定 进入linux系统 输入ip addr找到自己的网卡 我的是eno16777736 centos&#xff1a; 编辑 HWADDR"00:0C:29:54:CE:B8" TYPE"Ethernet" BOOTPROTO"…

公网IP多少钱可以购买?

公网IP是指可以在全球范围内访问和识别的唯一IP地址。对于许多企业和个人用户来说&#xff0c;公网IP是实现远程访问、搭建服务器、建立安全连接等重要需求的基础。公网IP的获取并不是免费的&#xff0c;并且价格因供应商和地区而异。 现有公网IP市场 当前&#xff0c;市场上有…

博弈论和sg函数

Nim游戏 题目链接&#xff1a;Nim游戏 先说结论&#xff1a;假设n堆石子&#xff0c;石子数分别为a1,a2,a3.....&#xff0c;则当a1^a2^a3^...^an0时先手必败&#xff0c;否则先手必胜。 因为所表示的二进制位必定是成对出现的&#xff0c;根据性质 1 ^ 1 0 &#xff0c;0 …

深入理解 pytest Fixture 方法及其应用

当涉及到编写自动化测试时&#xff0c;测试框架和工具的选择对于测试用例的设计和执行非常重要。在Python 中&#xff0c;pytest是一种广泛使用的测试框架&#xff0c;它提供了丰富的功能和灵活的扩展性。其中一个很有用的功 能是fixture方法&#xff0c;它允许我们初始化测试环…