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

详细介绍运算符重载函数,清晰明了

祝各位六一快乐~

前言

1.为什么要进行运算符重载?

C++中预定义的运算符的操作对象只能是基本数据类型。但实际上,对于许多用户自定义类型(例如类),也需要类似的运算操作。这时就必须在C++中重新定义这些运算符赋予已有运算符新的功能,使它能够用于特定类型执行特定的操作

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

2.什么是运算符重载 ?

运算符重载是通过创建运算符函数实现的,运算符函数定义了重载的运算符将要进行的操作。

1.基本知识

操作符重载,本质上就是函数重载(详细了解可点击阅读函数重载),它大大丰富了已有操作符的含义,方便使用

运算符重载格式如下:

1.函数名:operator+需要重载的运算符符号

2.函数原型:返回值类型 operator+符号(形参参数列表)

3.必须有一个类类型的参数

4.     ::    ?:    .      .*       sizeof  这五个运算符不能重载

5.用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义

6.作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐
藏的this

7.不能通过连接其他符号来创建新的操作符:比如operator@

8.运算符重载时必须遵循的原则

  • 重载运算符含义必须清楚;
  • 重载运算符不能有二义性。

9.算符函数重载的两种形式

  • 重载为类的成员函数
  • 重载为类的非成员函数 (非成员函数通常是友元函数)。

注:可以把一个运算符作为一个非成员、非友元函数重载。但是,这样的运算符函数访问类的私有和保护成员时,必须使用类的公有接口中提供的设置数据和读取数据的函数,调用这些函数时会降低性能。可以内联这些函数以提高性能。

补充知识:友元函数

一、友元函数的作用

  • 提供数据共享接口:为不同类之间的成员函数,以及类的成员函数与一般函数之间提供了数据共享的接口。
  • 支持类间紧密协作:当两个或多个类之间需要进行紧密的协作和交互时,友元函数允许直接访问私有成员,减少系统开销,提高效率。
  • 支持运算符重载:在某些情况下,可能需要重载运算符并操作两个不同对象之间的私有数据。此时可以将相应操作符重载函数声明为两个类的友元。

二、友元函数的特点(重点)

  • 与类的成员函数具有一样的权限:友元函数可以访问类的所有成员,包括私有成员。
  • 不属于任何类:友元函数是定义在类外的普通函数,不属于任何类。
  • 没有this指针:由于友元函数不是类的成员函数,因此它没有this指针。

三、友元函数的用法

  • 声明方式:友元函数需要在类中进行声明,前面需要加上friend关键字,可以放在公有部分也可以放在私有部分。
  • 多类友元:一个函数可以是多个类的友元函数,只需要在个各类中分别进行声明。
  • 调用方式:友元函数的调用与一般函数的调用方式和原理一致。

四、注意事项

  • 破坏封装性:友元函数破坏了类的封装性和类数据的隐藏性,因此在使用时需要谨慎考虑。
  • 避免过度使用:原则上应尽量少使用或不使用友元,除非确实能显著提高开发效率。

    2.经典运算符重载的代码示例(主要以日期类为例)

2.1operator+,operator-,operator+=,operator-=

以复数类为例

代码

#include<iostream>
using namespace std;//负数类
class complex
{
public:complex(double r = 0, double i = 0) :_real(r), _imag(i) {}complex operator +(const complex& c); //+运算符complex operator -(const complex& c);//-运算符complex& operator +=(const complex& c); //+=运算符complex& operator -=(const complex& c);//-=运算符complex& operator - ();//求负运算符void Print()const{cout << "(" << _real << "," << _imag << ")" << endl;}
private:double _real;//实部double _imag;//虚部
};
complex complex::operator +(const complex& c) //+运算符
{complex tmp;tmp._real = _real + c._real;tmp._imag = _imag + c._imag;return tmp;
}
complex complex::operator -(const complex& c) //-运算符
{complex tmp;tmp._real = _real - c._real;tmp._imag = _imag - c._imag;return tmp;
}
complex& complex::operator +=(const complex& c) //+=运算符
{_real += c._real;_imag += c._imag;return *this;
}
complex& complex::operator -=(const complex& c) //-=运算符
{_real -= c._real;_imag -= c._imag;return *this;
}
complex& complex::operator - ()//求负运算符
{_real = -_real;_imag = -_imag;return *this;
}
int main()
{complex c1(3.5, 5), c2(6, 8), c3, c4, c5;c3 = c1 + c2;c3.Print();c4 = c2 - c1;c4.Print();c1 += c2;c1.Print();c2.Print();c2 -= c1;c1.Print();c2.Print();c5 = -c2;c5.Print();return 0;
}

2.2前置operator++(--),后置operator++(--)

前置++和后置++的函数名都是operator++(没错,又是函数重载),他们的区别在于前置++没有形参,后置++有一个形参int,但是我们在实际上使用时并不需要给后置++的形参int传实参,int只是为了区分前置++和后置++的标识。

前置--和后置--也是同样用形参int来区分。

以日期类为例

#include<iostream>
using namespace std;
class Date
{
public:Date(int year = 0, int month = 0, int day = 0);// 拷贝构造函数// d2(d1)Date(const Date& d);// 获取某年某月的天数int GetMonthDay(int year, int month);// 日期+=天数Date& operator+=(int day);// 日期+天数Date operator+(int day)const;// 日期-=天数Date& operator-=(int day);// 日期-天数Date operator-(int day)const;// 前置++Date& operator++();// 后置++Date operator++(int);// 后置--Date operator--(int);// 前置--Date& operator--();void print()const;// 析构函数(日期类无需清理资源,析构函数不必显示写)//void print();//~Date()//{//cout << "~Date()" << endl;//}
private:int _year, _month, _day;
};Date::Date(int year, int month, int day)
{_year = year;_month = month;_day = day;
}
Date::Date(const Date& d)
{_year = d._year;_month = d._month;_day = d._day;
}
int Date::GetMonthDay(int year, int month)
{static int MonthDay[13] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };if (month == 2 && (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)){return 29;}else{return MonthDay[month];}
}
void Date::print()const
{cout << _year << "年" << _month << "月" << _day << "日" << endl;
}
Date& Date::operator+=(int day)
{if (day < 0){return *this -= -day;}_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month == 13){_month = 1;_year++;}}return *this;
}
Date Date::operator+(int day)const
{Date tmp = *this;tmp += day;return tmp;
}
Date& Date::operator-=(int day)
{if (day < 0){return *this += -day;}_day -= day;while (_day <= 0){_month--;if (_month == 0){_year--;_month = 12;}_day += GetMonthDay(_year, _month);}return *this;
}
Date Date::operator-(int day)const
{Date tmp = *this;tmp -= day;return tmp;
}
void Test1()
{Date d1(2024, 4, 30);Date d2 = d1 + 3;d2.print();Date d3(2024, 12, 31);Date d5 = d3;d3 += 1;d3.print();d5 = d5 - 1;d5.print();d1 -= 30;d1.print();Date d4 = d1 - 3;d4.print();
}
// 前置++
Date& Date::operator++()
{//这里直接用刚刚实现的Date& Date::operator+=(int day)//只是++相当于day=1而已//减少了代码负担*this += 1;return *this;
}
// 后置++
Date Date::operator++(int)
{//这里直接用刚刚实现的Date& Date::operator+(int day)Date tmp = *this;*this += 1;return tmp;
}
// 前置--
Date& Date::operator--()
{*this -= 1;return *this;
}
// 后置--
Date Date::operator--(int)
{Date tmp = *this;*this -= 1;return tmp;
}
void Test2()
{Date d1(2024, 6, 1);Date d2(2023, 12, 31);Date d3 = d1--;Date d4 = d2++;d3.print();d4.print();Date d5 = --d3;Date d6 = ++d4;d5.print();d6.print();
}
int main()
{//Test1();//可以自行测试Test2();
}

2.3operator<,operator<=,operator==,operator!=,operator>=,operator>

只需要实现operator<,operator==,其他的运算符重载就能轻松实现了,下面我们一起看一下吧

#include<iostream>
using namespace std;
class Date
{
public:Date(int year = 0, int month = 0, int day = 0);Date(const Date& d);// 获取某年某月的天数int GetMonthDay(int year, int month);// >运算符重载bool operator>(const Date& d);// ==运算符重载bool operator==(const Date& d);// >=运算符重载bool operator >= (const Date& d);// <运算符重载bool operator < (const Date& d);// <=运算符重载bool operator <= (const Date& d);// !=运算符重载bool operator != (const Date& d);void print()const;private:int _year, _month, _day;
};Date::Date(int year, int month, int day)
{_year = year;_month = month;_day = day;
}
Date::Date(const Date& d)
{_year = d._year;_month = d._month;_day = d._day;
}
int Date::GetMonthDay(int year, int month)
{static int MonthDay[13] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 };if (month == 2 && (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)){return 29;}else{return MonthDay[month];}
}
void Date::print()const
{cout << _year << "年" << _month << "月" << _day << "日" << endl;
}bool Date::operator < (const Date& d)
{if (_year < d._year){return true;}else if (_year == d._year){if (_month < d._month){return true;}else if (_month == d._month){if (_day < d._day){return true;}}}return false;
}
bool Date::operator == (const Date& d)
{return _year == d._year&&_month == d._month&&_day == d._day;
}
bool Date::operator != (const Date& d)
{return !(*this == d);
}
bool Date::operator <= (const Date& d)
{return *this < d || *this == d;
}
bool Date::operator > (const Date& d)
{return !(*this <= d );
}
bool Date::operator >= (const Date& d)
{return !(*this < d);
}
int main()
{Date d1(2024, 3, 2), d2(2023, 5, 6);cout << (d1 == d2) << endl;cout << (d1 != d2) << endl;cout << (d1 <= d2) << endl;cout << (d1 >= d2) << endl;cout << (d1 < d2) << endl;cout << (d1 > d2) << endl;
}

相关文章:

详细介绍运算符重载函数,清晰明了

祝各位六一快乐~ 前言 1.为什么要进行运算符重载&#xff1f; C中预定义的运算符的操作对象只能是基本数据类型。但实际上&#xff0c;对于许多用户自定义类型&#xff08;例如类&#xff09;&#xff0c;也需要类似的运算操作。这时就必须在C中重新定义这些运算符&#xff…...

国内外知名的低代码开发平台下载地址

以下是国内外几款低代码开发平台的列表&#xff0c;包含了下载地址、适应操作系统、是否可以独立部署、优点、缺点以及是否包含流程引擎的信息。 平台名称 下载地址 适应操作系统 是否可以独立部署 优点 缺点 是否包含流程引擎 国内平台 阿里云宜搭 阿里云官网 跨平台…...

【Pr学习】01新建项目起步

【Pr学习】01新建项目起步 1、新建项目2.序列设置2.1新建序列2.2序列参数讲解2.3自定义设置 3.PR窗口认识3.1 项目窗口3.2 源窗口2.4 保存面板 4.剪辑导入4.1 素材导入4.2 视图切换4.3 时间轴4.4轨道工具4.5 节目窗口素材导入 5.基础操作5.1 取消视频音频链接5.2 单独渲染&…...

【Redis延迟队列】redis中的阻塞队列和延迟队列

阻塞队列&#xff08;RBlockingQueue&#xff09; 作用和特点&#xff1a; 实时性&#xff1a;阻塞队列用于实时处理消息。生产者将消息放入队列&#xff0c;消费者可以立即从队列中取出并处理消息。阻塞特性&#xff1a;如果队列为空&#xff0c;消费者在尝试获取消息时会被…...

el-tree常用操作

一、定义 <el-treeclass"myTreeClass":data"dirTreeData":props"dirTreeProps":filter-node-method"filterDirTree":expand-on-click-node"false"node-key"id"node-click"dirTreeNodeClick":allow-…...

SQL 语言:存储过程和触发器

文章目录 基本概述创建触发器更改和删除触发器总结 基本概述 存储过程&#xff0c;类似于高阶语言的函数或者方法&#xff0c;包含SQL语句序列&#xff0c;是可复用的语句&#xff0c;保存在数据库中&#xff0c;在服务器中执行。特点是复用&#xff0c;提高了效率&#xff0c…...

Ubuntu Linux 24.04 使用certbot生成ssl证书

设置域名 1. 将需要生成SSL证书的域名解析到IP地址 idealand.xyz <> 64.176.82.190 检查防火墙的设置 1. 首先查看防火墙的状态&#xff1a; # ufw status 2. 如果防火墙开启了&#xff0c;要开放80和443端口用于certbot验证 # ufw allow 80 # ufw allow 443 生…...

Vivado 比特流编译时间获取以及FPGA电压温度获取(实用)

Vivado 比特流编译时间获取以及FPGA电压温度获取 语言 &#xff1a;Verilg HDL 、VHDL EDA工具&#xff1a;ISE、Vivado Vivado 比特流编译时间获取以及FPGA电压温度获取一、引言二、 获取FPGA 当前程序的编译时间verilog中直接调用下面源语2. FPGA电压温度获取&#xff08;1&a…...

Window下VS2019编译WebRTC通关版

这段时间需要实现这样一个功能&#xff0c;使用WebRTC实现语音通话功能&#xff0c;第一步要做的事情就是编译WebRTC源码&#xff0c;也是很多码友会遇到的问题。 经过我很多天的踩坑终于踩出来一条通往胜利的大路&#xff0c;下面就为大家详细介绍&#xff0c;编译步骤以及踩…...

【云原生 | 60】Docker中通过docker-compose部署kafka集群

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 &#x1f3c5;阿里云ACE认证高级工程师 &#x1f3c5;阿里云开发者社区专…...

allure测试报告用例数和 pytest执行用例数不相同问题

我出现的奇怪问题&#xff1a; pytest执行了9条用例&#xff0c;但是测试报告确只显示3条用例 我将其中的一个代码删除后&#xff0c;发现allure测试报告又正常了 我觉得很奇怪这个代码只是删除了二维数组的第一列&#xff0c;我检查了半天都找不到问题&#xff0c;只有降低版本…...

Ubuntu 离线安装 gcc、g++、make 等依赖包

前言 项目现场的服务器无法连接互联网&#xff0c;需要提前获取 gcc、g、make 等依赖包。 一、如何获取依赖包 需要准备一台可以连接互联网的电脑&#xff08;如&#xff1a;个人电脑上的虚拟机安装一个与服务器一样的系统&#xff09;&#xff0c;用于下载依赖包。之后把通过…...

Vxe UI vxe-upload 上传组件,显示进度条的方法

vxe-upload 上传组件 查看官网 https://vxeui.com 显示进度条很简单&#xff0c;需要后台支持进度就可以了&#xff0c;后台实现逻辑具体可以百度&#xff0c;这里只介绍前端逻辑。 上传附件 相关参数说明&#xff0c;具体可以看文档&#xff1a; multiple 是否允许多选 li…...

探索API接口:技术深度解析与应用实践

在当今的软件开发和数据交换领域&#xff0c;API&#xff08;应用程序编程接口&#xff09;已经成为了一个不可或缺的工具。它允许不同的软件应用程序或组件之间进行交互和通信&#xff0c;从而实现了数据的共享和功能的扩展。本文将深入探讨API接口的技术原理、设计原则以及在…...

ARM-V9 RME(Realm Management Extension)系统架构之系统安全能力的系统隔离属性

安全之安全(security)博客目录导读 目录 一、系统隔离属性 1、系统配置完整性 1.1、时间隔离 2、关键错误的报告 一、系统隔离属性 1、系统配置完整性 MSD必须确保任何可能危及其安全保证的系统寄存器的正确性和完整性。例如&#xff0c;MSD必须确认内存控制器配置是一致…...

一个班有n个学生,需要把每个学生的简单材料(姓名和学号)输入计算机保存。然后可以通过输入某一学生的姓名查找其有关资料。

当输入一个姓名后&#xff0c;程序就查找该班中有无此学生&#xff0c;如果有&#xff0c;则输出他的姓名和学号&#xff0c;如果查不到&#xff0c;则输出"本班无此人"。 为解此问题&#xff0c;可以分别编写两个函数&#xff0c;函数input_data用来输人n个…...

python的range() 函数

range() 函数 《红楼梦》&#xff0c;又名《石头记》&#xff0c;实际上是一颗神石在人间游历的故事。而这块石头&#xff0c;就是我们的主人公贾宝玉。神石在投胎成宝玉前&#xff0c;向茫茫大士和渺渺真人讲起了自己的故事&#xff1a; 女娲氏炼石补天之时&#xff0c;于大…...

ClickHouse数据管理与同步的关键技术

2024年 5 月 18 日&#xff0c;ClickHouse官方首届杭州 Meetup 活动成功举行。本次活动由 ClickHouse 和阿里云主办&#xff0c;NineData 和云数据库技术社区协办。围绕ClickHouse的核心技术、应用案例、最佳实践、数据管理、以及迁移同步等方面&#xff0c;和行业专家展开交流…...

【一竞技DOTA2】东南亚Bleed战队官宣Emo正式加盟

1、近日东南亚Bleed战队正式发布公告官宣&#xff0c;中国选手Emo以及来自蒙古选手Se加盟战队。 【公告内容如下】 我们很高兴宣布&#xff0c;战队DOTA2名单中添加了两位新成员&#xff0c;请和我们一起欢迎来自中国经验丰富的老将Emo以及来自蒙古的后起之秀Se 一号位&#…...

算法学习笔记(7.3)-贪心算法(最大切分乘问题)

目录 ##问题描述 ##问题思考 ##贪心策略确定 ##代码实现 ##时间复杂度 ##正确性验证 ##问题描述 给定一个正整数 &#x1d45b; &#xff0c;将其切分为至少两个正整数的和&#xff0c;求切分后所有整数的乘积最大是多少 ##问题思考 假设我们将 &#x1d45b; 切分为 &…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

接口自动化测试:HttpRunner基础

相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具&#xff0c;支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议&#xff0c;涵盖接口测试、性能测试、数字体验监测等测试类型…...