C++学习笔记----8、掌握类与对象(六)---- 操作符重载(2)

news2024/10/9 9:08:32

1.3、第三次尝试:全局operator+

        隐式转换允许你使用operator+成员函数给SpreadsheetCell对象加上int与double。然而,这个操作符不是双向的,如下代码所示:

	aThirdCell = myCell + 5.6;
	aThirdCell = myCell + 4;
	aThirdCell = 5.6 + myCell; // FAILS TO COMPILE!
	aThirdCell = 4 + myCell;   // FAILS TO COMPILE!

        当SpreadsheetCell对象在操作符左侧的时候可以很好地进行隐式转换,但是当在右边的时候就不灵光了。另外假定是双向的,其实也有问题。问题就是operator+成员函数必须在SpreadsheetCell对象上进行调用,该对象必须在operator+的左手边。c++语言就是这么定义的。所以是没有办法让operator+成员函数按那种方式工作的。

        然而,如果把类内的operator+成员函数用全局的operator+函数替换,不与任何特定对象紧密绑定在一起,就可以解决这个问题了。函数看起来像这样:

SpreadsheetCell operator+(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs)
{
	return SpreadsheetCell { lhs.getValue() + rhs.getValue() };
}

        需要在模块接口文件中声明该操作符并export出来:

export class SpreadsheetCell
{
    /* Omitted for brevity */
};

export SpreadsheetCell operator+(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs);

        现在所有的四个前面的相加操作都可以按你想要的结果工作了。

	aThirdCell = myCell + 5.6;    // works fine
	aThirdCell = myCell + 4;    // works fine
	aThirdCell = 5.6 + myCell; // works fine
	aThirdCell = 4 + myCell;   // works fine

        你可能会想,如果按下面的代码写会有什么结果:

aThirdCell = 4.5 + 5.5;

        它会正常编译并执行,但是不会调用你写的operator+。它会执行正常的double相加4.5与5.5,结果是下面的中间语句:

aThirdCell = 10;

        为了使这个赋值语句好好干活,应该在右手边有一个SpreadsheetCell对象。编译器发现有一个非显式的用户定义的构造函数使用一个double参数,会使用这个构造函数隐式地将double值转换成一个临时的SpreadsheetCell对象,然后会调用赋值操作符。

2、重载算术操作符

        现在你理解了怎么写operator+,那剩下的基本算术操作术就很直接了。下面是+,-,*,与/的声明,可以用<op>来替换+,-,*,与/,结果就是四个函数。也可以重载%,但是对于保存在SpreadsheetCell中的double值是讲不通的,没必要凑数了。

export class SpreadsheetCell { /* Omitted for brevity */ };
export SpreadsheetCell operator<op>(const SpreadsheetCell& lhs,
    const SpreadsheetCell& rhs);

        operator-与operator*的实现与operator+的实现类似,所以就不赘述了。对于operaotr/,稍有点儿不同,记住要检查是否被零除。如果检测到被零除要抛出一个例外:

SpreadsheetCell operator/(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs)
{
	if (rhs.getValue() == 0) {
		throw invalid_argument { "Divide by zero." };
	}
	return SpreadsheetCell { lhs.getValue() / rhs.getValue() };
}

                c++不要求在operator*真正实现乘,在operator/中实现除,等等。你可以在operator/中实现乘,在operator/中实现除,等等。然而,那样会非常地令人迷惑,没有道理这么做啊。只要有可能,在实现中用通常的用过的操作符的意思就行了。

注意:在c++中,不要改变操作的运算优先级。例如,*与/要比+与-早检查。一旦运算的优先级定了,用户定义的操作符唯一需要做的事就是去实现。c++也不允许你发明新的操作符号或者改变操作符的参数数量。我们以后还会再详细讨论操作符重载。

2.1、重载算术缩写操作符

        除了简单的算术操作符,c++提供了像+=与-=这样的缩写操作符。你可能想当然地认为在类中写了operator+,它就会提供operator+=。对不起,你没有这么走运。你不得不显式地重载缩写算术操作符。这些操作符与基本的算术操作述不同,它们改变了操作符左手边的对象而不是生成一个新对象。第二个细微的不同是,与赋值操作符相似,它们产生了一个指向被改变对象的引用结果。

        算术缩写操作符总是要求左手边的类的对象,所以要把它们写成成员函数,而不是全局函数。下面是SpreadsheetCell类的定义:

export class SpreadsheetCell
{
public:
	SpreadsheetCell& operator+=(const SpreadsheetCell& rhs);
	SpreadsheetCell& operator-=(const SpreadsheetCell& rhs);
	SpreadsheetCell& operator*=(const SpreadsheetCell& rhs);
	SpreadsheetCell& operator/=(const SpreadsheetCell& rhs);
    // Omitted for brevity
}

        operator+=的实现,其它的类似。

SpreadsheetCell& SpreadsheetCell::operator+=(const SpreadsheetCell& rhs)
{
	set(getValue() + rhs.getValue());
	return *this;
}

        缩写的算术操作符是基本算术与赋值操作符的组合。有了前面的定义,你可以写出下面的代码:

	SpreadsheetCell myCell { 4 }, aThirdCell{ 2 };
	aThirdCell -= myCell;
	aThirdCell += 5.4;

        但是,你不能写出下面这样的代码(有这种想法也是很奇葩!)

5.4 += aThirdCell;

        注意:当同时有正常的与缩写版本的某个操作符时,推荐使用正常的那个而不是缩写版本的,以避免代码重复。

        下面是一个例子:

SpreadsheetCell operator+(const SpreadsheetCell& lhs, const SpreadsheetCell& rhs)
{
	auto result{ lhs };  // Local copy
	result += rhs;       // Forward to +=()
	return result;
}

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

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

相关文章

<<迷雾>> 第10章 用机器做一连串的加法(2)--寄存器 示例电路

使用多个触发器可以构成一个寄存器 info::操作说明 单击按钮开关产生上升沿信号, 将 D 的输入存在 Q 端 primary::在线交互操作链接 https://cc.xiaogd.net/?startCircuitLinkhttps://book.xiaogd.net/cyjsjdmw-examples/assets/circuit/cyjsjdmw-ch10-02-register-by-multipl…

《Programming from the Ground Up》阅读笔记:p147-p180

《Programming from the Ground Up》学习第9天&#xff0c;p147-p180总结&#xff0c;总计34页。 一、技术总结 1.Physical memeory p152, Physical memory refers to the actual RAM chips inside your computer and what they contain. 物理地址指的RAM&#xff0c;即我们…

Kubernetes网络通讯模式深度解析

Kubernetes的网络模型建立在所有Pod能够直接相互通讯的假设之上&#xff0c;这构建了一个扁平且互联的网络空间。在如GCE&#xff08;Google Cloud Engine&#xff09;等云环境中&#xff0c;这一网络模型已预先配置&#xff0c;但在自建的Kubernetes集群中&#xff0c;我们需要…

深圳市步步精科技有限公司成功获得插头结构及电连接器发明专利

2024年8月20日&#xff0c;深圳市步步精科技有限公司&#xff08;以下简称“步步精”&#xff09;喜讯传来&#xff0c;公司申请的“插头结构和电连接器”专利&#xff08;授权公告号CN 118399121 B&#xff09;正式获得授权。这项创新的插头结构在数据线连接领域具有重要的应用…

[含文档+PPT+源码等]精品基于Nodejs实现的家教服务小程序的设计与实现

基于Node.js实现的家教服务小程序的设计与实现背景&#xff0c;主要源于以下几个方面&#xff1a; 一、家教市场的现状与需求 随着教育竞争的日益激烈&#xff0c;家庭对子女教育质量的重视程度不断提升&#xff0c;家教服务已成为许多家庭不可或缺的一部分。然而&#xff0c…

第三方软件测评机构简析:软件安全测试报告的内容和作用

随着数字化时代的到来&#xff0c;软件的安全性显得尤为重要。尤其在信息安全事件频发的今天&#xff0c;软件安全测试报告成为企业和开发者关注的焦点。软件安全测试报告是评估软件系统安全性的一种综合性文档&#xff0c;通常在软件开发生命周期中进行安全性测试后生成。 软…

计算机毕业设计 | SpringBoot 房屋租赁网 租房买房卖房平台(附源码)

1&#xff0c;绪论 1.1 背景调研 在房地产行业持续火热的当今环境下&#xff0c;房地产行业和互联网行业协同发展&#xff0c;互相促进融合已经成为一种趋势和潮流。本项目实现了在线房产平台的功能&#xff0c;多种技术的灵活运用使得项目具备很好的用户体验感。 这个项目的…

银河麒麟桌面操作系统中使用ufw开启防火墙

银河麒麟桌面操作系统中使用ufw开启防火墙 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 在银河麒麟桌面操作系统里&#xff0c;开启防火墙只需一个简单的步骤。 打开终端&#xff0c;然后执行命令&#xff1a; sudo ufw enable这样就能…

Auth2.0单点登录(企业开发流程)

实习中接到需求单点登录&#xff0c;记录一下单点登录在企业中的实际应用。其实单点登录在不同的业务中处理细节还是不相同的&#xff0c;我这里仅举例我们这个需求中如何处理的一种情形。 一.概念 简单来说就是一次登录&#xff0c;各处访问。 二.流程 场景一&#xff1a;…

Spring源码二IOC容器源码

文章目录 Spring IOC初始化源码剖析1.prepareRefresh2.obtainFreshBeanFactory3.prepareBeanFactory4.postProcessBeanFactory5.invokeBeanFactoryPostProcessors6.registerBeanPostProcessors7.initMessageSource8.initApplicationEventMulticaster9.onRefresh10.registerList…

Day05-数据库服务索引应用

Day-05-数据库索引知识说明 1、数据库索引概述介绍2、数据库索引分类介绍3、数据库索引应用配置4、数据库执行计划概述5、数据库执行计划获取7、数据库索引覆盖长度8、数据库联合索引应用 01.数据库索引概述介绍 02.数据库索引分类介绍 03.数据库索引应用配置 04.数据库执行计划…

C高级(Day25)

一、学习内容 Shell脚本 shell中的变量 shell中变量的定义 shell中的变量是没有数据类型的&#xff0c;&#xff0c;默认是字符串 shell中的变量默认是全局变量 格式 变量名 错误&#xff0c;计算机认为变量名是一个指令 变量名 正确&#xff0c;定义变量 &#xff0c;值为空…

基于Springboot+Vue的公寓出租系统 (含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 这个系…

成都睿明智科技有限公司靠谱吗怎么样?

在这个短视频与直播带货风起云涌的时代&#xff0c;抖音电商凭借其庞大的用户基数和高效的流量转化能力&#xff0c;成为了众多商家争相入驻的新蓝海。而在这场电商盛宴中&#xff0c;专业的服务商如成都睿明智科技有限公司&#xff0c;更是成为了连接品牌与消费者的桥梁。那么…

Win10 安装 Redis 数据库

一、Redis 数据库介绍 Redis 是一个开源的高性能键值对&#xff08;key-value&#xff09;的非关系型数据库。它通常用作数据结构服务器&#xff0c;支持多种类型的数据结构&#xff0c;如字符串&#xff08;strings&#xff09;、哈希&#xff08;hashes&#xff09;、列表&a…

同城O2O系统源码与跑腿配送平台的架构设计与开发方案详解

今天&#xff0c;笔者将与您一同深入探讨同城O2O系统的源码及跑腿配送平台的架构设计与开发方案&#xff0c;助力开发者和企业在这一领域的实践与探索。 一、O2O系统概述 在同城O2O模式中&#xff0c;用户可以通过手机应用或网页平台下单&#xff0c;而配送员则根据订单信息迅…

redis高级(面试题一)

目录 一、Redis持久化机制有哪些&#xff1f;有什么区别&#xff1f; 1、RDB(redis database) 2、AOF 3、区别 二、redis的主从集群有什么用&#xff1f; 1、什么是redis的主从集群 2、为什么要使用redis主从集群&#xff08;也就是有什么用&#xff09; 三、redis的哨兵…

ORA-19815 db_recovery_file_dest_size 100%

1、alert日志报错 ORA-19815 db_recovery_file_dest_size 100% 恢复区空间使用满 2、rm删除后操作系统空间使用&#xff0c;但V$RECOVERY_FILE_DEST记录的空间使用率仍然是满的 3、rman delete expired 归档日志后恢复正常 4、当然可以通过增大db_recovery_file_dest_size来临时…

算法笔记(十四)——多源 BFS

文章目录 <font colorred>01 矩阵<font colorred>飞地的数量/font>地图中的最高点地图分析 多源 BFS 单源最短路问题&#xff1a;一个起点到一个终点的最短路&#xff1b; 解决步骤&#xff1a; 把起点放进队列里一层一层往外扩 相关文章&#xff1a;算法笔记&a…

0基础跟德姆(dom)一起学AI 机器学习04-逻辑回归

逻辑回归简介 应用场景 逻辑回归是解决二分类问题的利器 数学知识 sigmoid函数 概率 极大似然估计 核心思想&#xff1a; 设模型中含有待估参数w&#xff0c;可以取很多值。已经知道了样本观测值&#xff0c;从w的一切可能值中&#xff08;选出一个使该观察值出现的概率为…