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

目录

 

前言

运算符重载

概念

目的

写法

调用

注意事项

详解注意事项

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

类中隐含的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; //实例化d

	Date d1(d);  //示例化d1,并把d的值拷贝给d1

	Date d2 = d;  //示例化d2,并把d的值拷贝给d2

	Date d3;  //实例化d3

	d3 = 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; //实例化对象d
	Date d1; //实例化对象d1

	d = 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 

本篇的内容到此结束啦

 

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

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

相关文章

Scikit-Learn

机器学习中的重要角色 Scikit-Leran&#xff08;官网&#xff1a;https://scikit-learn.org/stable/&#xff09;&#xff0c;它是一个基于 Python 语言的机器学习算法库。Scikit-Learn 主要用 Python 语言开发&#xff0c;建立在 NumPy、Scipy 与 Matplotlib 之上&#xff0c;…

嵌入式中strstr函数详解

一、strstr函数是什么? strstr函数是 C 语言中的一个标准库函数(使用时要引入头文件string.h),用于在一个字符串中查找另一个字符串首次出现的位置。如果找到子串,则返回子串在主串中首次出现的位置的指针;如果未找到,则返回 NULL。 二、使用场景 1.用来找出字符串1在字…

学习了解大模型的四大缺陷

由中国人工智能学会主办的第十三届吴文俊人工智能科学技术奖颁奖典礼暨2023中国人工智能产业年会于2024年4月14日闭幕。 会上&#xff0c;中国工程院院士、同济大学校长郑庆华认为&#xff0c;大模型已经成为当前人工智能的巅峰&#xff0c;大模型之所以强&#xff0c;是依托了…

GPT国内怎么用

2022年11月&#xff0c;OpenAI发布了ChatGPT&#xff0c;这标志着大型语言模型在自然语言处理领域迈出了巨大的一步。ChatGPT不仅在生成文本方面表现出了惊人的流畅度和连贯性&#xff0c;更为人工智能应用开启了全新的可能性。 ChatGPT的推出促进了人工智能技术在多个领域的广…

网工交换技术基础——VLAN原理

1、VLAN的概念&#xff1a; VLAN(Virtual LAN)&#xff0c;翻译成中文是“虚拟局域网”。LAN可以是由少数几台家用计算机构成的网络&#xff0c;也可以是数以百计的计算机构成的企业网络。VLAN所指的LAN特指使用路由器分割的网络——也就是广播域。 2、VLAN的主要作用&#xf…

stm32f103c8t6学习笔记(学习B站up江科大自化协)-SPI

SPI通信 SPI&#xff0c;&#xff08;serial peripheral interface&#xff09;&#xff0c;字面翻译是串行外设接口&#xff0c;是一种通用的数据总线&#xff0c;适用于主控和外挂芯片之间的通信&#xff0c;与IIC应用领域非常相似。 IIC无论是在硬件电路还是在软件时序设计…

JUC知识点三

执行TestFrames这个类的时候发生了什么呢&#xff1f; 执行TestFrames这个类的时候发生了什么呢&#xff1f; 1、首先执行一个类加载&#xff0c;把TestFrames这个类的二进制字节码加载到java虚拟机中的方法区内存中&#xff08;其实是二进制的字节码&#xff0c;只是为了好理…

linux运行ant 报错 Unable to locate tools.jar【已解决】

linux安装 ant 运行时报错 Unable to locate tools.jar. Expected to find it in /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.402.b06-1.el7_9.x86_64/lib/tools.jar 原因 已安装的jdk只有运行环境&#xff0c;没有tool.jar&#xff0c;而ant运行需要java开发环境&#xff0c;因…

如何进行数据库的迁移与同步——【DBA 从入门到实践】第四期

在日常的数据库运维工作中&#xff0c;我们时常会面临数据库替换、机房搬迁、业务测试以及数据库升级等任务&#xff0c;这些任务都需要对数据进行迁移和同步操作。【DBA 从入门到实践】第4期&#xff0c;将引导大家深入了解数据库迁移的流程&#xff0c;并探讨在迁移过程中可用…

Zynq学习笔记--AXI 总线仿真(AXI VIP)

目录 1. 概述 2. Simulation with AXI VIP 2.1 axi_vip_pkg 2.2 design_1_axi_vip_0_0_pkg 2.3 参数指定 3. 实例化注意事项 3.1 名称对应关系 3.2 寄存器地址 3.3 block design 1. 概述 AXI Verification IP&#xff08;AXI VIP&#xff09;是一种用于验证AXI总线协议的…

无需公网IP,安全稳定实现U8C异地访问

无需公网IP&#xff0c;安全稳定实现U8C异地访问 用友是全球领先的企业云服务与软件提供商&#xff0c; 在财务、人力、供应链、采购、制造、营销、研发、项目、资产、协同等领域为客户提供数字化、智能化、社会化的企业云服务产品与解决方案。 U8C是用友针对成长型、创新型…

ElasticSearch中使用向量和关键词联合检索

注&#xff1a;案例测试数据及其索引构建详见&#xff1a;ElasticSearch中使用bge-large-zh-v1.5进行向量检索&#xff08;一&#xff09;-CSDN博客 中的第三部分。 假设任务场景为&#xff1a;用“新疆”向量检索相关的数据&#xff0c;同时需要匹配关键词“巴州”。 首先获取…

最新免费 ChatGPT、GPTs、AI换脸(Suno-AI音乐生成大模型)

&#x1f525;博客主页&#xff1a;只恨天高 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ ChatGPT3.5、GPT4.0、GPTs、AI绘画相信对大家应该不感到陌生吧&#xff1f;简单来说&#xff0c;GPT-4技术比之前的GPT-3.5相对来说更加智能&#xff0c;会根据用户的要求生成多种内容…

基于快照行情的股票/基金 1分钟 K 线合成指南

1. 概述 由于不同交易所不同资产的交易规则是有差异的&#xff0c;导致不同交易所基于快照行情或逐笔成交合成不同资产1分钟 K 线的计算方法是不同的。 本教程旨在提高 DolphinDB 在具体业务场景下的落地效率&#xff0c;降低 DolphinDB 在实际业务使用中的开发难度。 本教程…

文章解读与仿真程序复现思路——中国电机工程学报EI\CSCD\北大核心《含状态耦合约束的分布式船舶储能系统两层能量管理方法》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

计算机科学与导论 第十六章 安全

文章预览&#xff1a; 16.1引言16.1.1 安全目标16.1.2 攻击 16.2机密性16.2.1 对称密钥密码术16.2.2 非对称密钥密码术 16.1引言 为了安全&#xff0c;信息需要避开未授权的使用(机密性),保护信息不受到未授权的篡改(完整性)&#xff0c;并且对于得到授权的实体来说是需要时可…

uniapp之消除图片的空白占用空间

我们在使用uniapp开发的过程中一定会遇到一个情况就是我们加载的图片总有一点空白出现在不该出现的地方代码如下 <view style"background:#ff0000;"><image style"width:100%;"src"https://t7.baidu.com/it/u1819248061,230866778&fm19…

selenium_定位输入框并输入值_CLASS_NAME

找到class_name # 导包 from selenium import webdriver from time import sleep# 获取浏览器对象 from selenium.webdriver.common.by import Bydriver webdriver.Edge() # 打开url url r"C:\Users\黄永生\Desktop\软件测试\tpshop\web自动化_day01_课件笔记资料代码\0…

【面试经典 150 | 链表】分隔链表

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;模拟 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容进行回顾…

关于macOS 10.13-10.15系统安装教程

关于macOS 10.13-10.15系统安装教程 1、关机状态按完电源键&#xff0c;或重启黑屏后&#xff0c;按住option键不放&#xff0c;直到进入启动菜单&#xff1b; 2、选择启动U盘&#xff0c;开始跑进度条&#xff0c;跑完后进入如下界面&#xff1a; 安装界面语言选择&#xff0c…