《C++避坑神器·十八》运算符重载,小白也能看懂

news2024/11/28 22:41:37

对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型

1、对于+号运算符没有类 = 类 + 类,现在要给+号赋予对象可以相加的功能
(1)成员函数重载+号运算符
在这里插入图片描述
(2)全局函数重载+号运算符
在这里插入图片描述
(3)也可以把+号赋予为类 = 类 + 整形
在这里插入图片描述
在这里插入图片描述
总结:
(1)什么时候可以用运算符重载?参数是类、结构体或者枚举
(2)自定义数据类型可以改变运算符含义,具体怎么改变还原本质来看,比如operator+(Person &p, int i)就可以知道对+号运算符重载,具体实现怎么的加法还原本质:Person p3 = operator+(p1, 10); 可以知道p3 = p1 + 10;
(3)成员函数重载运算符只能有一个传参,具体是怎么定义+号的还原本质:Person p3 = p1.operator+(10); 可以知道p3 = p1 + 10;

2、<<运算符重载
cout << p; //直接输出对象,这样写错误,现在修改<<运算符让它这样写可以输出p对象内容

(1)成员函数重载<<运算符

void operator<<(cout)
{
}

本质是p.operator<<(cout),简化就是p << cout,反了,所以采用成员函数重载<<运算符行不通。

(2)全局函数重载<<运算符
在这里插入图片描述
如果cout << p1 << endl; 这样又报错了,因为这样写的本质是一个链式编程cout << p1得要有返回值才能继续<< endl; 所以做如下改进:

在这里插入图片描述
返回值ostream &加&的目的就是不管返回多少次一直是这个cout,cout << p1 << endl;先执行cout << p1返回cout,然后cout << endl;进行换行,如果不加&,第一次返回本身cout后会有个ostream类的对象接收cout,调用了拷贝构造,此时的cout不在是本身,这里设为cout’,即cout’ << endl;报错,因为cout是唯一的,只有cout本身才包含换行。

通常类中的变量都会设为私有,这样的话operator函数调用成员变量就报错了,这里可以引入全局函数做友元访问类中私有变量:
在这里插入图片描述

3、对前置++和后置++重定义

(1)重定义前置++

在这里插入图片描述
先实现可以直接打印对象p的值cout << p
实现前置++的函数不知道返回什么可以先设为void,内部实现对象p值的自增,但cout << ++p这样错误,现在只认cout << p,所以要保证重定义++函数能够返回一个对象,这样cout << ++p实际是cout << p(p是自增后的)

这是成员函数重载前置++的写法
在这里插入图片描述

(2)重定义后置++

在这里插入图片描述
后置++要知道一点,重定义函数中返回原来对象的值,然后原来对象值自增,这就需要借助中间对象tmp先接收对象p本身所有变量(拷贝构造),然后对象本身p值自增,最后返回原先的对象p这里返回tmp已经接收了原先p所有属性。
为什么不返回引用?
如果返回引用则一直针对的是对象tmp本身,而tmp对象是局部的在函数运行结束销毁,销毁后就无法根据tmp获取对象p值,所以直接返回对象,每次tmp都是不同的。我只要每次tmp能接收到对象p所有属性并能返回就行了,不需要每次都只针对同一个tmp。

注意:如果一个类中同时有前置++和后置++重定义函数

Person & operator++() {} //前置++重定义
Person operator++() {} //后置++重定义

这样会报错,除了返回值不同其他都一样,但返回值不同不能作为函数重载条件,这时候需要在后置++重定义函数中加个占位参数来和前置++进行函数重载予以区分前置和后置

Person operator++(int) {}

在这里插入图片描述
注意:后置++要有占位符

全局函数重定义后置++运算符:
在这里插入图片描述
可以看出如果同时存在前置++和后置++重定义函数,后置++需要有个占位参数来区分。

4、重定义=运算符

在这里插入图片描述
前面说到过C++编译器至少给一个类添加了三个默认函数,无参构造、拷贝构造(浅拷贝)和析构函数,学到这里还有一个默认函数实际是给一个类添加了四个默认函数,第四个为重定义=运算符函数(浅拷贝)。
有个注意的地方:
Person p1;
Person p2 = p1; //这里用到的是默认的拷贝构造,浅拷贝
p2 = p1; //这里用到的是默认的重定义=运算符函数,浅拷贝
以前一直以为p2 = p1也是调用默认拷贝构造,现在才知道是调用默认重定义=运算符函数。
在上面的例子中如果不手动写重定义=运算符函数,默认的则为:

void operator=(const Person& p)
{
	age = p.age  //两个对象指针指向同一块内存空间,造成多次释放同一块内存空间报错
}

这样就需要手动写重定义=运算符函数,在内部进行深拷贝。

我们注意到=号是可以连=的,即p2 = p1 = p; 这就需要operator=函数返回对象,如下图:

在这里插入图片描述
(应该return p才对,不是return * this )
p2 = p1 = p,加引用返回的一直是p对象本身,其实不加引用也没事只不过每次接收的p都是新的p,比较浪费内存空间,不如加引用一直针对一个对象本身。而且内部做了一个判断,为啥要先判断age是否在堆区?
Person p;
Person p1 = p(这里就当作用了深拷贝,这样p1在堆区有数据)
p1 = p; //这样做就相当于在重定义函数中又在堆区重新申请了内存进行深拷贝,那之前申请的内存空间要释放掉,不然会造成资源空间浪费,所以要先判断是否有属性在堆区,有就释放掉,然后重新申请内存进行深拷贝。这样的话C++提供的默认重定义函数如下:

Person& operator=(const Person& p)
{
	age = p.age;
	return *this;
}

5、自定义重载关系运算符

(1)自定义重载==运算符
在这里插入图片描述

6、函数调用运算符重载

函数调用运算符()可以重载,由于重载后使用方式非常像函数调用,因此称为仿函数,仿函数没有固定写法,非常灵活。
在这里插入图片描述
在这里插入图片描述
这里需要知道什么是匿名函数对象:

Person p = Person(); //这是第二种方法初始化对象
Person(); //这是匿名对象,用完就销毁
Person()(1, 2); //这是匿名对象和重载()运算符函数融合,称作匿名函数对象
在这里插入图片描述

📢博客主页: 主页
📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
📢本文由 梦回阑珊 原创,首发于 CSDN,转载注明出处🙉
📢代码改变世界,你来改变代码!✨

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

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

相关文章

行情分析——加密货币市场大盘走势(11.16)

大饼昨日突然回调诱多上涨到38000附近&#xff0c;现在又重新跌回到37500&#xff0c;现在仓位小的可以加仓入场&#xff0c;而已经有仓位的不要动即可。 空单策略&#xff1a;入场37500附近 止盈34000-32000 止损39000 以太今日可以入场空单2060附近即可 策略&#xff1a;入…

Databend 源码阅读: Storage 概况和 Read Partitions

作者&#xff1a;zhyass | Databend Labs 成员&#xff0c;数据库研发工程师 ❤️ 友情提示&#xff1a;代码演进较快&#xff0c;请注意文档的时效性哦&#xff01; 引言 Databend 将存储引擎抽象成一个名为 Table 的接口&#xff0c;源码位于 query/catalog/src/table.rs。…

2023年9月 少儿编程 中国电子学会图形化编程等级考试Scratch编程一级真题解析(选择题)

2023年9月scratch编程等级考试一级真题 选择题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 1、下列哪项内容是不可以修改的 A、角色名称 B、造型名称 C、背景名称 D、舞台名称 答案&#xff1a;D 考点分析&#xff1a;考查scratch相关知识&am…

centos搭建docker镜像Harbor仓库的简明方法

在kubernetes集群中如果要部署springcloud这样的应用&#xff0c;就必须有一个自建的docker镜像中心仓库。 它的目的有两点&#xff1a; 1. 镜像拉取速度快 2. 开发好维护 而Harbor是一个非常好用的docker本地仓库 所以本篇文章来讲讲如何在部署Harbor仓库 首先系统版本最…

tegra nvidia agx xaiver 系统开机自动启动风扇配置方法

确保系统可以连接到互联网&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 1.更新系统软件源&#xff1a; sudo apt-get update2.安装pip工具 sudo apt-get install python-pip3.安装nvidia对应工具 sudo -H pip install jetson-stats4.打开NVI…

华为eNSP综合实验考试

VLAN信息表 设备名称 端口 链路类型 VLAN 参数 HZ-HZCampus-Agg01-S5731 GE0/0/1 Trunk PVID:1 Allow-pass&#xff1a;10 20 Eth-trunk1&#xff08;GE0/0/2,0/0/3,0/0/23&#xff09; Trunk PVID:1 Allow-pass&#xff1a;10 20 GE0/0/24 Access PVID&#xf…

Leetcode 33 搜索旋转排序数组

class Solution {//旋转数组从中间分开&#xff0c;总有一侧是有序的&#xff0c;一侧是无序的//只需要判断是否在有序区间就可以进行二分查找public int search(int[] nums, int target) {int left 0, right nums.length - 1;while(left < right){int mid (left right)…

小红书直播开启新纪元,拓世法宝AI直播一体机助您轻松成为行业标杆!

2023年&#xff0c;小红书终于成功坐上了电商牌桌。 今年3月的“董洁效应”带动了一批品牌商家、博主入驻小红书试水&#xff0c;其直播业务积蓄了巨大势能。10月15日&#xff0c;“初代名媛”章小蕙完成了在小红书的第二场直播&#xff0c;以销售额破亿的成绩打响了小红书双1…

Chrome开发者模式去除时间轴

经常用chrome调试&#xff0c;发现时间轴用的不多&#xff0c;想屏蔽掉。 参考&#xff1a;滑动验证页面 我做了截图记录下

众安保险面试题

文章目录 1.说一下Java内存模型?2.List、Set、Map的区别?3.介绍一下设计模式?4.MySQL存储结构?5.索引失效的场景?6.为什么使用函数索引会失效?7.Spring事务有哪两种?7.1 编程式事务@RestController7.2 声明式事务8.@Transactional实现原理?9.事务如何合并@Transactiona…

卡码网语言基础课 | 12. 位置互换

通过本次练习&#xff0c;将要学习到以下C知识点&#xff1a; 位置互换交换变量字符串 题目&#xff1a;给定一个长度为偶数位的字符串&#xff0c;请编程实现字符串的奇偶位互换。 奇偶位互换是指字符串的奇数位和偶数位相互交换位置 即&#xff1a;第一位和第二位交换&…

服装供应链管理的革新利器—超高频RFID技术

一、行业概述 服装行业一直被视为低技术含量的劳动密集型产业&#xff0c;但实际上&#xff0c;科学技术在整个行业的发展中起着至关重要的作用&#xff0c;从服装面料的制作到服装设计、生产制作、物流到终端销售&#xff0c;科技力量贯穿于每一个环节。然而&#xff0c;传统…

城市生命线丨城市燃气管网监测系统功能效果

11月6日&#xff0c;福建泉州某小区发生煤气闪爆导致1死三伤&#xff0c;这起事故再次为我们敲响了城市燃气管网安全监测的警钟。在城市生命线的建设中&#xff0c;城市燃气管网监测系统以其独特的作用和价值&#xff0c;成为保障城市安全的重要一环。 根据应急管理部《全国城镇…

Flex布局---看一篇就够了

1. flex布局是什么&#xff1f; flex是flexible Box的缩写&#xff0c;用来为盒装模型提供的最大的灵活性&#xff0c;任何一个容器都可以指定为flex布局。Flex布局称为flex容器&#xff0c;所有的子元素为容器成员Flex项目&#xff08;flex item&#xff09;&#xff1b; 当为…

ES7升级、jar包升级、工具类封装,代码改造

一、spring-data-elasticsearch 引入es版本适配 二、jar升级 在项目工程根pom.xml文件中增加maven依赖管理在这里插入图片描述 <properties><elasticsearch.spring.version>4.2.0</elasticsearch.spring.version><elasticsearch.version>7.12.0</e…

JS-项目实战-更新水果单价更新小计更新总计

1、fruit.js //当页面加载完成后执行后面的匿名函数 window.onload function () {//get:获取 Element:元素 By:通过...方式//getElementById()根据id值获取某元素let fruitTbl document.getElementById("fruit_tbl");//table.rows:获取这个表格的所有的行&a…

echarts点击事件、柱状图设置区间颜色

实现echarts柱状图标记区域&#xff0c;并在单击柱状条时触发点击事件切换标记区域 //html <div id"main" style"width: 600px;height:400px;"></div>//js let _chart null; letselectInfo {};//选择的柱状条信息&#xff0c;可用于信息的获…

【iDRAC】突破错误信息壁垒,利用iDRAC提高效率

序 面对旧服务器上的黄色警示灯&#xff0c;工作人员往往陷入困惑。更糟糕的是&#xff0c;如果该服务器转手多次&#xff0c;缺少root用户密码和IP地址&#xff0c;那么要访问服务器iDRAC就更困难了。但是出现问题的硬件蕴含着重要信息&#xff0c;为了解开这个谜团&#xff…

Linux Docker图形化工具Portainer如何进行远程访问?

文章目录 前言1. 部署Portainer2. 本地访问Portainer3. Linux 安装cpolar4. 配置Portainer 公网访问地址5. 公网远程访问Portainer6. 固定Portainer公网地址 前言 Portainer 是一个轻量级的容器管理工具&#xff0c;可以通过 Web 界面对 Docker 容器进行管理和监控。它提供了可…