C++——运算符重载

一、运算符重载

①含义

函数重载或函数多态:同名函数完成相同的基本操作
C++将重载的概念扩展到运算符上,于是出现了运算符重载

C++中有很多运算符已经被重载
*运算符,运用于地址,可以得到存储在这个地址的值;运用于两个数字,得到是两个数字的乘积
C++会根据操作数的数目和类型来决定采用哪种操作
C++允许将运算符重载扩展到用户定义的类型中,例如类,允许使用+将两个对象相加

②格式

operatorop(argument-list)
例如:operator+()operator*()
其中op必须是一个有效的C++运算符,不能虚构,例如:operator@(),C++中没有@运算符

假设有一个Animal类有两个对象,dog和cat,并定义了operator+()成员函数重载+运算符,当两个对象相加时,编译器发现操作数都是Animal对象,则会使用相应的运算符函数来进行替换
animal = dog + cat;
animal = dog.operator+(cat);

二、实操举例

小明早上上班通勤花费2h35min,晚上下班通勤花费2h40min,则一天上下班共花费多少时间在通勤上?

Ⅰ重载常规做法

①time.h

定义一个Time类,当分钟超过59时,函数AddMinutes()和Sum()方法会使用整数除法和求模运算符进行调整

#pragma once
#ifndef TIME_H_
#define TIME_H_class Time 
{
private:int hour_;int minute_;public:Time();Time(int hours, int minutes);void AddMinutes(int minutes);void AddHours(int hours);void Reset(int hours = 0, int minutes = 0);Time Sum(const Time& time) const;void PrintTime() const;
};#endif // !TIME_H_

②time.cpp

不要返回执行局部变量或临时对象的引用,函数执行完毕后,局部变量和临时对象都会消失,引用将指向不存在的数据
这里的Sum函数返回类型是Time,而非引用

#include <iostream>
#include "time.h"Time::Time() 
{hour_ = 0;minute_ = 0;
}Time::Time(int hour, int minute)
{hour_ = hour;minute_ = minute;
}void Time::AddMinutes(int minutes) 
{minute_ += minutes;hour_ += minute_ / 60;minute_ %= 60;
}void Time::AddHours(int hours) 
{hour_ += hours;
}void Time::Reset(int hour, int minute) 
{hour_ = hour;minute_ = minute;
}//Time,返回类型是Time,而不是引用;返回类型不能是引用,需要创建对象的副本;若为返回类型为引用时,sum对象是局部变量,函数结束会被删除
//const Time& t,参数是引用
Time Time::Sum(const Time& t) const
{Time sum;sum.minute_ = minute_ + t.minute_;sum.hour_ = hour_ + t.hour_ + sum.minute_ / 60;sum.minute_ %= 60;return sum;
}void Time::PrintTime() const 
{std::cout << hour_ << ":" << minute_ << std::endl;
}

③main.cpp

#include <iostream>
#include "time.h"int main() 
{Time go_to_work(2, 45);Time work_time(6, 30);Time go_home(3, 15);Time total_time;std::cout << "go_to_work time is: ";go_to_work.PrintTime();std::cout << std::endl;std::cout << "work_time time is: ";work_time.PrintTime();std::cout << std::endl;std::cout << "go_home time is: ";go_home.PrintTime();std::cout << std::endl;total_time = go_to_work.Sum(work_time.Sum(go_home));std::cout << "total_time is: ";total_time.PrintTime();std::cout << std::endl;return 0;
}

运行结果:
在这里插入图片描述
可以看到,上班通勤2h45min,工作6h30min,下班通勤3h15min,一天总用12h30min

Ⅱ重载加法运算符

常规做法看起来很麻烦
total_time = go_to_work.Sum(work_time.Sum(go_home));

不如直接使用重载加法运算符操作便捷
total_time = go_to_work + work_time + go_home;

重载加法运算符很简单,只需要将Sum()改成operator+()即可

①time.h

原先:Time Sum(const Time& time) const;
现在:Time operator+(const Time& time) const;

#pragma once
#ifndef TIME_H_
#define TIME_H_class Time
{
private:int hour_;int minute_;public:Time();Time(int hours, int minutes);void AddMinutes(int minutes);void AddHours(int hours);void Reset(int hours = 0, int minutes = 0);//Time Sum(const Time& time) const;Time operator+(const Time& time) const;void PrintTime() const;
};#endif // !TIME_H_

②time.cpp

原先:Time Time::Sum(const Time& t) const
现在:Time Time::operator+(const Time& t) const

#include <iostream>
#include "time.h"Time::Time() 
{hour_ = 0;minute_ = 0;
}Time::Time(int hour, int minute)
{hour_ = hour;minute_ = minute;
}void Time::AddMinutes(int minutes) 
{minute_ += minutes;hour_ += minute_ / 60;minute_ %= 60;
}void Time::AddHours(int hours) 
{hour_ += hours;
}void Time::Reset(int hour, int minute) 
{hour_ = hour;minute_ = minute;
}/*
//Time,返回类型是Time,而不是引用;返回类型不能是引用,需要创建对象的副本;若为返回类型为引用时,sum对象是局部变量,函数结束会被删除
//const Time& t,参数是引用
Time Time::Sum(const Time& t) const
{Time sum;sum.minute_ = minute_ + t.minute_;sum.hour_ = hour_ + t.hour_ + sum.minute_ / 60;sum.minute_ %= 60;return sum;
}
*/
Time Time::operator+(const Time& t) const
{Time sum;sum.minute_ = minute_ + t.minute_;sum.hour_ = hour_ + t.hour_ + sum.minute_ / 60;sum.minute_ %= 60;return sum;
}void Time::PrintTime() const 
{std::cout << hour_ << ":" << minute_ << std::endl;
}

③main.cpp

原先:total_time = go_to_work.Sum(work_time.Sum(go_home));
现在:total_time = go_to_work.operator+(work_time.operator+(go_home));
等价于:total_time1 = go_to_work + work_time + go_home;

在运算符表示法中,运算符左侧的对象(go_to_work )是调用对象,运算符右边的对象(work_time + go_home)是作为参数被传递的对象

+运算符是从左向右结合的运算符
首先work_time.operator+(go_home)返回一个Time对象,work_timego_home的和,然后这个和作为go_to_work.operator+()的参数,得到go_to_workwork_timego_home之和

#include <iostream>
#include "time.h"int main() 
{Time go_to_work(2, 45);Time work_time(6, 30);Time go_home(3, 15);Time total_time, total_time1;std::cout << "go_to_work time is: ";go_to_work.PrintTime();std::cout << std::endl;std::cout << "work_time time is: ";work_time.PrintTime();std::cout << std::endl;std::cout << "go_home time is: ";go_home.PrintTime();std::cout << std::endl;//total_time = go_to_work.Sum(work_time.Sum(go_home));total_time = go_to_work.operator+(work_time.operator+(go_home));total_time1 = go_to_work + work_time + go_home;std::cout << "total_time is: ";total_time.PrintTime();std::cout << std::endl;std::cout << "total_time1 is: ";total_time1.PrintTime();std::cout << std::endl;return 0;
}

运行结果:
在这里插入图片描述

三、限制

看到这里,我想家人们应该会理解了,运算符重载其实就是这么一回事,没那么难
说白了就是operatorop去替代函数名称而已,例如operator+()替代Sum()

运算符重载理解了,家人们可以随意去发挥去秀操作,但运算符重载是有限制的

重载的运算符不必是成员函数,但必须至少有一个操作数是用户定义的类型!
使用运算符时不能反运算符原来的句法规则,例如不能将求模运算符(%)重载成使用一个操作数,例如int x; Time t; % x; % t;
同样不能修改运算符的优先级,若将+运算符重载为两个类相加,则新的运算符与原来的+具有相同的优先级

还有一些运算符不可以重载,家人们可以去网上搜索一下对应的表格

以下是不可重载的运算符和可重载的运算符

1,不可重载的运算符:
在这里插入图片描述
2,可重载的运算符
在这里插入图片描述

本篇博文参考《C++ Primer Plus(第6版)》若有侵权,联系立删

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

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

相关文章

IPv6的地址类型

IPv6地址总长度为128bit&#xff0c;被分为8组&#xff0c;每组为4个十六进制数&#xff0c;用冒号分隔&#xff1a; 例如&#xff1a;FC00:0123:4567:8901:ABFD:0987:0000:0023 可缩写为&#xff1a;FC00:0123:4567:8901:ABFD:0987::23 IPv6中取消了v4中的广播&#xff0c;新…

矢量网络分析仪(VNA)基础解析与应用指南

矢量网络分析仪&#xff08;VNA&#xff09;是一种极其精密的仪器&#xff0c;能够对电气网络的阻抗进行表征&#xff0c;测量结果可提供幅度和相位细节&#xff0c;从而深入了解其行为。被测设备&#xff08;DUT&#xff09;通常用于射频&#xff08;RF&#xff09;应用&#…

工厂+策略模式之最佳实践(疾病报卡维护模块API设计)

目录 &#x1f4bb;业务场景 &#x1f527;应用技术 ⚙概要流程 ❗开发注意 服务类上标注了 自定义注解 却无法直接利用getDeclaredAnnotation 获取 *Spring代理机制 代理机制的工作原理 代理的工作机制 代理的使用场景 已获取EmrXXXServiceImpl 的Class&#xff0c;如…

ARM异常处理 M33

1. ARMv8-M异常类型及其详细解释 ARMv8-M Exception分为两类&#xff1a;预定义系统异常(015)和外部中断(1616N)。 各种异常的状态可以通过Status bit查看&#xff0c;获取更信息的异常原因&#xff1a; CFSR是由UFSR、BFSR和MMFSR组成&#xff1a; 下面列举HFSR、MMFSR、…

【单片机通讯协议】—— 常用的UART/I2C/SPI等通讯协议的基本原理与时序分析

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、通信基本知识1.1 MCU的参见外设1.2 通信的分类按基本的类型从传输方向上来分 二、UART&#xff08;串口通讯&#xff09;2.1 简介2.2 时序图分析2.3 UART的…

Adversarial Machine Learning(对抗机器学习)

之前把机器学习&#xff08;Machine Learning&#xff09;的安全问题简单记录了一下&#xff0c;这里有深入研究了一些具体的概念&#xff0c;这里记录一下方便以后查阅。 Adversarial Machine Learning&#xff08;对抗机器学习&#xff09; Adversarial Examples 相关内容Eva…

【Go】context标准库

文章目录 1. 概述1.1 什么是 Context1.2 设计原理1.3 使用场景1.4 Context 分类核心:Context接口2. 源码解读4个实现emptyCtxTODO 和 BackgroundcancelCtxWithCancelcancelCtx.propagateCancel 构建父子关联parentCancelCtx 获取父上下文中的内嵌cancelCtxcanceltimerCtxWithT…

解决 vue3 中 echarts图表在el-dialog中显示问题

原因&#xff1a; 第一次点开不显示图表&#xff0c;第二次点开虽然显示图表&#xff0c;但是图表挤在一起&#xff0c;页面检查发现宽高只有100px,但是明明已经设置样式宽高100% 这可能是由于 el-dialog 还没有完全渲染完成&#xff0c;而你的 echarts 组件已经开始尝试渲染图…

计算机网络习题( 第3章 物理层 第4章 数据链路层 )

第3章 物理层 一、单选题 1、下列选项中&#xff0c;不属于物理层接口规范定义范畴的是&#xff08; &#xff09;。 A、 接口形状 B、 引脚功能 C、 传输媒体 D、 信号电平 正确答案&#xff1a; C 2、在物理层接口特性中&#xff0c;用于描述完成每种功能的事件发…

通俗易懂!使用Excel和TF实现Transformer

本文旨在通过最通俗易懂的过程来详解Transformer的每个步骤&#xff01; 假设我们在做一个从中文翻译到英文的过程&#xff0c;我们的词表很简单如下&#xff1a; 中文词表&#xff1a;[机、器、学、习] 英文词表[deep、machine、learning、chinese] 先来看一下Transformer的…

智慧楼盘二维、三维组件融合 720三维全景可视化

本系统通过数字孪生技术&#xff0c;实现小区楼盘系统的可视化展示&#xff0c;整合楼盘内各个系统的数据源&#xff0c;将楼盘模型与房间模型、720三维全景图相结合&#xff0c;实现了从楼盘周边到室内布局的全方位展示&#xff0c;为购房者提供全方位的可视化信息。 整个项目…

QT QCombox QSS样式问题

/*combobox 样式*/ QComboBox#FileterComboBox,QComboBox#DateRangeComboBox{background-color: #262626; /* 背景颜色 */color: #e0e0e0; /* 文本颜色 */border-radius:16px;font-family: "Microsoft YaHei"; /* 文本字体族 */font-size: 18px; /* 文…

Unittest02|TestSuite、TestRunner、HTMLTestRunner、处理excel表数据、邮件接收测试结果

目录 八、测试套件TestSuite和测试运行器TestRunner 1、基本概念 2、创建和使用测试套件 3、 自动发现测试用例、创建测试套件、运行测试 4、生成html的测试报告&#xff1a;HTMLTestRunner 1️⃣导入HTMLTestRunner模块 2️⃣运行测试用例并生成html文件 九、unittest…

NIPS2014 | GAN: 生成对抗网络

Generative Adversarial Nets 摘要-Abstract引言-Introduction相关工作-Related Work对抗网络-Adversarial Nets理论结果-Theoretical Results实验-Experiments优势和不足-Advantages and disadvantages缺点优点 结论及未来工作-Conclusions and future work研究总结未来研究方…

【已解决】pyinstaller打包ico图片报错:OSError: [WinError 225] 无法成功完成操作,因为文件包含病毒或潜在的垃圾软件。

起因&#xff1a; pyinstaller加上 --icon 参数打包时报错。 命令如下&#xff1a; 解决&#xff1a; 关闭 Windows 的病毒防护即可&#xff0c;步骤如下。 点屏幕右下角通知栏&#xff0c;进入“病毒和威胁防护”&#xff1a; 打开&#xff1a; 关闭实时保护&#xff08…

011-spring-整合三方框架的命名空间原理(重要)

根据context标签来学习了解 <context:property-placeholder location"jdbc.properties"/> <bean id"dataSource" class"com.alibaba.druid.pool.DruidDataSource"><property name"driver" value"${db.driver}&quo…

No.29 笔记 | CTF 学习干货

大家好呀&#xff01;我刚参加了美国线上CTF比赛&#xff0c;收获超多&#xff0c;特别感谢老师教我的干货知识。今天就和大家分享我的学习笔记。CTF像刺激冒险&#xff0c;有挑战有惊喜。 学习中我懂了很多知识技能&#xff0c;像密码学、Web安全、Misc题型等&#xff0c;它们…

sonarqube 安装及使用

一、官网参考地址 相关版本下载地址 配置全局变量 .bash_profileexport SONAR_HOME=/Users/jd/soft/sonar-scanner-6.2.1.4610 export PATH=$PATH:$SONAR_HOME/bin export SQ_HOST=http://127.0.0.1:9000/ export SQ_TOKEN=squ_dbb1913e095a92a727a918a9ba6b1af94b007748二、…

使用ArcGIS/ArcGIS pro绘制六边形/三角形/菱形渔网图

在做一些尺度分析时&#xff0c;经常会涉及到对研究区构建不同尺度的渔网进行分析&#xff0c;渔网的形状通常为规则四边形。构建渔网的方法也很简单&#xff0c;使用ArcGIS/ArcGIS Pro工具箱中的【创建渔网/CreateFishnet】工具来构建。但如果想构建其他形状渔网进行相关分析&…

pytorch MoE(专家混合网络)的简单实现。

专家混合&#xff08;Mixture of Experts, MoE&#xff09;是一种深度学习模型架构&#xff0c;通常用于处理大规模数据和复杂任务。它通过将输入分配给多个专家网络&#xff08;即子模型&#xff09;&#xff0c;然后根据门控网络&#xff08;gating network&#xff09;的输出…