当前位置: 首页 > news >正文

【C++】运算符重载详解

💗个人主页💗
⭐个人专栏——C++学习⭐
💫点击关注🤩一起学习C语言💯💫

目录

导读

1. 为什么需要运算符重载

2. 运算符重载概念

3. 运算符重载示例

3.1 == 运算符重载

3.2 >或<运算符

4. 运算符重载参数

5. 全局运算符重载函数

6. 赋值运算符重载

6.1 语法及概念

6.2 示例

6.3 为何使用引用


导读

前面我们学习了默认成员函数:构造函数、析构函数和拷贝构造函数。

今天我们来学习赋值运算符重载。

1. 为什么需要运算符重载

我们一般的运算符只能对于数字进行运算,或是比较大小,但是如果我们想要对我们所定义的自定义类型进行运算呢?

为了使自定义类型能够支持运算符操作,可以通过运算符重载的方式来重新定义这些运算符,使其能够在自定义类型上执行特定的操作。

比如我们定义了一个日期类,想要对这个日期类进行加减运算,亦或是比较两个日期的大小,通过运算符重载即可实现。

2. 运算符重载概念

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其 返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字为:关键字operator后面接需要重载的运算符符号。

函数原型:返回值类型 operator操作符(参数列表)

一般来说需要遵循以下几个原则:

  1. 运算符的重载必须定义在类、结构体或枚举中。

  2. 运算符重载函数必须使用特殊的命名约定,以指示要重载的运算符。

  3. 运算符重载函数可以是类的成员函数,也可以是非成员函数。

  4. 运算符重载函数的参数和返回值类型应该与运算符原有的操作数类型相匹配。

  5. 运算符重载函数可以使用其他的运算符或已有的函数来实现其操作。

3. 运算符重载示例

3.1 == 运算符重载

我们来判断两个日期是否相等:

我们需要依次比较年、月、日。

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}//operator运算符 做函数名bool operator == (const Date& y){return _year == y._year&& _month == y._month&& _day == y._day;}private:int _year;int _month;int _day;
};int main()
{Date d1(2024, 2, 02);Date d2(2024, 2, 03);cout << d1.operator ==  (d2) << endl;return 0;
}

我们知道,运算符重载也是默认成员函数之一,也就是我们不去调用,编译器也会自动帮我们调用。

比如:

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}//operator运算符 做函数名bool operator == (const Date& y){return _year == y._year&& _month == y._month&& _day == y._day;}private:int _year;int _month;int _day;
};int main()
{Date d1(2024, 2, 3);Date d2(2024, 2, 2);cout << d1.operator ==  (d2) << endl;cout << (d1 == d2) << endl;return 0;
}

3.2 >或<运算符

判断两个日期的大小:

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}//operator运算符 做函数名bool operator < (const Date& y){if (_year < y._year){return true;}else if (_year == y._year){if (_month < y._month){return true;}else if (_month == y._month){return _day < y._day;}}return false;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2024, 1, 28);Date d2(2024, 1, 29);cout << d1.operator < (d2) << endl;cout << (d1 < d2) << endl;return 0;
}

4. 运算符重载参数

上述我们的代码明明是对两个日期进行比较,为何只有一个参数呢?

运算符重载函数的参数取决于要重载的运算符的操作数个数和类型。

  1. 一元运算符重载:一元运算符只有一个操作数。在重载一元运算符时,通常将其定义为类的成员函数,没有参数(除了隐式的this指针)。

  2. 二元运算符重载:二元运算符有两个操作数。在重载二元运算符时,可以选择将其定义为类的成员函数或非成员函数。

    • 如果将二元运算符定义为类的成员函数,参数列表将包括一个额外的参数,表示右侧操作数。左侧操作数则是隐式的this指针。

    • 如果将二元运算符定义为非成员函数(全局函数或友元函数),参数列表将包括两个参数,分别表示左侧和右侧操作数。

5. 全局运算符重载函数

我们依旧对比两个日期是否相等,判断大小,注意与上述代码的参数差异。

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}//private:int _year;int _month;int _day;
};//operator运算符 做函数名
bool operator == (const Date& x, const Date& y)
{return x._year == y._year&& x._month == y._month&& x._day == y._day;
}bool operator < (const Date& x, const Date& y)
{if (x._year < y._year){return true;}else if (x._year == y._year){if (x._month < y._month){return true;}else if (x._month == y._month){return x._day < y._day;}}return false;
}
int main()
{Date d1(2024, 1, 28);Date d2(2024, 1, 29);cout << operator == (d1, d2) << endl;cout << operator < (d1, d2) << endl;cout << (d1 == d2) << endl;cout << (d1 < d2) << endl;return 0;
}

6. 赋值运算符重载

6.1 语法及概念

赋值运算符重载是一种特殊的运算符重载,用于在自定义的类中重载"="运算符,使其能够对类对象进行正确的赋值操作。

赋值运算符重载的语法如下:

class ClassName {
public:ClassName& operator=(const ClassName& other) {// 执行赋值操作的代码return *this;}
};

在赋值运算符重载函数中,通常需要执行以下操作:

  1. 检查是否是自我赋值,即当前对象和要赋值的对象是否是同一个对象。如果是同一个对象,则直接返回当前对象,避免不必要的操作。

  2. 进行属性的深拷贝,将要赋值的对象的属性逐个复制给当前对象的属性。

  3. 返回当前对象的引用。

6.2 示例

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << '/' << _month << '/' << _day << endl;}Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}private:int _year;int _month;int _day;
};int main()
{Date d1(2024, 2, 01);Date d2(2024, 2, 02);Date d3(2024, 2, 03);d1 = d2 = d3;d1.Print();d2.Print();d3.Print();return 0;
}

6.3 为何使用引用

  1. 引用参数:赋值运算符需要修改当前对象的值,而不是创建一个新的对象。因此,使用引用参数,可以直接修改当前对象而不是在函数内部创建一个副本。

  2. 返回this指针:赋值运算符一般返回当前对象的引用,即*this。这样可以实现连续赋值操作,例如 a = b = c。通过返回this指针,可以链式调用赋值运算符。

相关文章:

【C++】运算符重载详解

&#x1f497;个人主页&#x1f497; ⭐个人专栏——C学习⭐ &#x1f4ab;点击关注&#x1f929;一起学习C语言&#x1f4af;&#x1f4ab; 目录 导读 1. 为什么需要运算符重载 2. 运算符重载概念 3. 运算符重载示例 3.1 运算符重载 3.2 >或<运算符 4. 运算符重…...

评论区功能的简单实现思路

评论区功能是社交类项目中的核心组成部分&#xff0c;它涉及到前端的交云和后端的数据处理。基于你的技术栈&#xff08;前端 Vue3&#xff0c;后端 Java&#xff09;&#xff0c;下面是一个具体的实现思路和数据库设计建议&#xff0c;并探索一下知乎的评论系统。 数据库设计…...

Java自救手册

目录 访问地址 访问地址&#xff0c;发现不通&#xff0c;无法访问&#xff1a; 网络不通一般有两种情况&#xff1a; Maven 拿Maven 拿到Maven以后 Maven单独的报红 Git git注意&#xff1a; 目录 访问地址 访问地址&#xff0c;发现不通&#xff0c;无法访问&…...

ASM-HEMT参数提取和模型验证测试

参数提取程序 直流I-V参数提取 DC模型参数提取流程对于ASM-GaN-HEMT模型可以总结在下图中。 以下步骤描述了该流程&#xff1a; 在模型中设置物理参数&#xff0c;如L&#xff08;沟道长度&#xff09;、W&#xff08;沟道宽度&#xff09;、NF&#xff08;栅指数&#xf…...

浅压缩、深压缩、双引擎、计算机屏幕编码……何去何从?

专业视听领域尤其显示控制和坐席控制领域&#xff0c;最近几年最激动人心的技术&#xff0c;莫过于分布式了。 分布式从推出之日就备受关注&#xff1a;担心稳定性的&#xff0c;质疑同步性能的&#xff0c;怀疑画面质量的…… 诚然&#xff0c;我们在此前见多了带着马赛克的…...

2020年通信工程师初级专业实务真题

文章目录 一、第1章 现代通信网概述&#xff1a;信令网、同步网、管理网。第10章 通信业务&#xff1a;通信产业链&#xff0c;通信终端的分类&#xff0c;通信业务的定义及分类二、第3章 接入网&#xff1a;无线接入网的优点&#xff0c;接入网的接口&#xff08;UNI&#xff…...

Linux常见面试题汇总

Linux上如何查询某个端口是否被占用&#xff1f; 在Linux上&#xff0c;你可以使用以下几种方法来查询某个端口是否被占用&#xff1a; 使用netstat命令&#xff1a; netstat -tuln | grep <端口号>这个命令会列出当前正在运行的所有TCP和UDP端口&#xff0c;并过滤出指…...

C语言小游戏:贪吃蛇(游戏开发的环境和功能介绍)

❀❀❀ 文章由不准备秃的大伟原创 ❀❀❀ ♪♪♪ 若有转载&#xff0c;请联系博主哦~ ♪♪♪ ❤❤❤ 致力学好编程的宝藏博主&#xff0c;代码兴国&#xff01;❤❤❤ 生命不停&#xff0c;学习不止。铁汁们&#xff0c;我是大伟&#xff0c;欢迎来到大伟的游戏时间&#xff0c…...

ElementUI Form:InputNumber 计数器

ElementUI安装与使用指南 InputNumber 计数器 点击下载learnelementuispringboot项目源码 效果图 el-radio.vue &#xff08;InputNumber 计数器&#xff09;页面效果图 项目里el-input-number.vue代码 <script> export default {name: el_input_number,data() {re…...

apk反编译修改教程系列---修改apk的默认颜色 布局颜色 手机电脑同步演示【十】

往期教程&#xff1a; apk反编译修改教程系列-----修改apk应用名称 任意修改名称 签名【一】 apk反编译修改教程系列-----任意修改apk版本号 版本名 防止自动更新【二】 apk反编译修改教程系列-----修改apk中的图片 任意更换apk桌面图片【三】 apk反编译修改教程系列---简单…...

响应式开发如何设置断点,小屏幕界面该如何显示(有动图)

Hi&#xff0c;我是贝格前端工场&#xff0c;本期分享响应式开发&#xff0c;如何设置屏幕断点&#xff0c;pc页面布局到了移动端之后该如何布局的问题&#xff0c;微软也提供了设置屏幕断点的动图演示&#xff0c;非常直观。 一、什么是响应式开发&#xff0c;为何要设置屏幕断…...

Java基础 集合(二)List详解

目录 简介 数组与集合的区别如下&#xff1a; 介绍 AbstractList 和 AbstractSequentialList Vector 替代方案 Stack ArrayList LinkedList 前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界…...

UE4运用C++和框架开发坦克大战教程笔记(十七)(第51~54集)

UE4运用C和框架开发坦克大战教程笔记&#xff08;十七&#xff09;&#xff08;第51~54集&#xff09; 51. UI 框架介绍UE4 使用 UI 所面临的问题以及解决思路关于即将编写的 UI 框架的思维导图 52. 管理类与面板类53. 预加载与直接加载54. UI 首次进入界面 51. UI 框架介绍 U…...

GaussDB新体验,新零售选品升级注入新思路【华为云GaussDB:与数据库同行的日子】

选品思维&#xff1a;低频VS高频 一个的商超&#xff0c;假设有50个左右的品类&#xff0c;每个品类下有2到10个不等的商品。然而如此庞大的商品&#xff0c;并非所有都是高频消费品。 结合自身日常的消费习惯&#xff0c;对于高频和低频的区分并不难。一般大型家电、高端礼盒…...

C语言问题汇总

指针 #include <stdio.h>int main(void){int a[4] {1,2,3,4};int *p &a1;int *p1 a1;printf("%#x,%#x",p[-1],*p1);} 以上代码中存在错误。 int *p &a1; 错误1&#xff1a;取a数组的地址&#xff0c;然后1&#xff0c;即指针跳过int [4]大小的字节…...

QT 的 blockSignals(true) 的作用范围

在 Qt 中&#xff0c;blockSignals 是一个用于控件的方法&#xff0c;它用于阻止控件发出的信号。如果你在一个 MainWindow 对象上调用 blockSignals(true)&#xff0c;它会阻止该 MainWindow 对象发出的所有信号。 这意味着&#xff0c;如果 MainWindow 上有任何子控件&#…...

【C++私房菜】类和对象万字详解

目录 一、类与对象 1、类是什么 二、类和对象的基础知识 2.1 定义类&#xff1a;成员变量和成员函数 2.2 创建对象&#xff1a;实例化一个类的对象。 2.3对象的生命周期&#xff1a;构造函数和析构函数。 a. 构造函数 b. 析构函数 c.小结&#xff1a; 三、成员变量和…...

PDF下载添加水印和访问密码

下载接口 ApiOperation(value "下载文件-pdf", notes "下载文件pdf版", httpMethod "GET", response WebResult.class)RequestMapping(value "/downloadPdf", method RequestMethod.GET)public void downloadFilePdf(RequestPar…...

基于SSM+MySQL的的新闻发布系统设计与实现

目录 项目简介 项目技术栈 项目运行环境 项目截图 代码截取 源码获取 项目简介 新闻发布系统是一款基于Servletjspjdbc的网站应用程序&#xff0c;旨在提供一个全面且高效的新闻发布平台。该系统主要包括后台管理和前台新闻展示两个平台&#xff0c;涵盖了新闻稿件的撰写…...

记录首次使用yolov8-obb

1.数据格式 之前使用的数据格式是yolov5_obb的数据格式&#xff0c;然后需要转数据格式&#xff1a; 目前的数据只支持四个坐标点标注的数据&#xff0c;参考&#xff1a;If a corner of the rotate rectangle is out of the image range, How to annotate the image? Issu…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...