运算符重载函数

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


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


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


 

下面以日期类为例子

我们知道系统的基本类型可以进行,+、-等基本运算,但是用户的自定义类型,我们不能使用系统的基本类型+和-,需要对其进行函数名重载才能使用这些操作。

运算符既可以是成员函数,也可以是非成员函数。因为我们通常将用户自定义类型的数据定义为私有,在类外不能访问私有成员。所以通常,将运算符重载函数,定义为成员函数。特别注意,成员函数的形参列表,形参的个数比实际的个数少一个。因为有一个是这个类本身。

#pragma once#define _CRT_SECURE_NO_WARNINGS#include <iostream>
#include <cassert>
using namespace std;class Date
{
public:Date(int year = 1, int month = 1, int day = 1){if (month >= 13 || month <= 0|| day >= GetMonthDay(year, month) || day <= 0){assert(false);}_year = year;_month = month;_day = day;}Date& operator=(const Date& d);bool operator<(const Date& d) const;bool operator==(const Date& d) const;bool operator<=(const Date& d) const;bool operator>=(const Date& d) const;bool operator>(const Date& d) const;bool operator!=(const Date& d) const;Date operator+(int day);Date& operator+=(int day);int GetMonthDay(int year, int month);Date& operator++();Date operator++(int);Date& operator-=(int day);Date operator-(int day);Date operator--(int);Date& operator--();int operator-(const Date& d);friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);private:int _year;int _month;int _day;
};

=的运算符重载

Date& Date::operator=(const Date& d) 
{if (this != (&d)){_year = d._year;_month = d._month;_day = d._day;}return *this;
}

等号运算符重载的返回值为Date& 类型,使用的是赋值后对象的自引用,可以减少拷贝,提高效率。如果this==&d,说明是自己对自己赋值,不需要进行操作。

==运算符重载

bool Date::operator==(const Date& d) const
{return _year == d._year && _month == d._month && _day == d._day;
}

==号运算符的重载判断年、月、日是否相等就可以了。

下面就是<、<=、>=、>等运算符的重载

<运算符的重载

bool Date::operator<(const Date& d) const
{if (_year < d._year){return true;}else if (_year == d._year && _month < d._month){return true;}else if (_year == d._year && _month == d._month && _day < d._day){return true;}return false;}

<=运算符的重载

在前面,我们已经实现过<、==的运算符重载。只需要复用前面的代码就可以实现<=的运算符重载。

bool Date::operator<=(const Date& d) const
{return (*this < d) || (*this == d);
}

>运算符的重载

>的反面就是<=,我们对<=取反就可以完成,>运算符的重载。

bool Date::operator>(const Date& d) const
{return !(*this <= d);
}

>=运算符的重载

>=的反面是<,只需要对<取反就可以完成>=的操作了。

bool Date::operator>=(const Date& d) const
{return !(*this < d);
}

!=运算符的重载

!=是==的反面

bool Date::operator>(const Date& d) const
{return !(*this <= d);
}

+=、+、-=、-运算符的重载

+=运算符的重载

int Date::GetMonthDay(int year,int month)
{int Arry[13] = { 0,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 Arry[month] + 1;}else{return Arry[month];}
}Date& Date::operator+=(int day)
{if (day < 0){return (*this) -= -day;}else{_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);++_month;if (_month == 13){_month = 1;++_year;}}return *this;}}

如果一个类+=day,我们先将这个类的_day+day,再判断_day的天数,有没有大于这个月的天数,如果大于了,类的月份+1,月份+1后判断,月份是否超过了12,超过了的话将月份置为1,年份+1.循环往复,就可以就出+day后的日期了。

如果+=一个负数的天数,实际上是-=一个整数的天数,我们调用-=就好了。

+运算符的重载

+运算符和+=运算符类似。

比如: int a=3; 

a+3返回结果6,但是a还是3

a+=3,返回6,a变成了6

Date Date::operator+(int day)
{Date tmp = (*this);tmp += day;return tmp;}

-=运算符的重载

Date& Date::operator-=(int day)
{if (day < 0){return (*this) += -day;}else{_day -= day;while (_day <= 0){--_month;if (_month == 0){_month = 12;--_year;}_day += GetMonthDay(_year, _month);}return *this;}}

-=运算符的操作和+=的类似,我们先把类的_day-=day;如果得到一个负数,说明日期的_day不足以-day,我们需要向月份借天数,将月份--,然后_day+=借的那个月的天数。月份--之后,我们需要对月份判断是否正确,如果本来月份是1,--变成0,实际上是去年的12月,需要将_month=12,还有减少年份。之后就需要循环判断,直到_day>0为止。

-运算符的重载

-和-=运算符类似

Date Date::operator-(int day)
{Date tmp = (*this);tmp -= day;return tmp;
}

++、--运算符的重载

++运算符的重载

++分为前置++与后置++

前置++运算符的重载

前置++返回的是++后的结果

Date& Date::operator++()
{*this = *this + 1;return *this;
}

后置++的运算符重载

我们怎么区分前置和后置呢,在形参列表加入一个int就可以说明这个是后置++了。这个int便于编译器区分。

后置++返回的是++之前的结果,++的数据仍然就行了自增。

Date Date::operator++(int)
{Date tmp = (*this);*this =(*this)+1;return tmp;
}

前置--运算符重载函数

Date& Date::operator--()
{(*this) -= 1;return *this;
}

后置--运算符重载函数

Date Date::operator--(int)
{Date tmp = (*this);*this -= 1;return tmp;
}

那么我们如何计算两个日期相差多少天呢。利用日期-时期。所以需要我们构造日期-日期的运算符重载函数。

int Date::operator-(const Date& d)
{Date max=(*this);Date min=d;int flag = 1;if (*this < d){max = d;min = (*this);flag = -1;}int n = 0;while (min != max){min++;n++;}return flag*n;
}

两个日期相减,我们需要先找到两个中较大的日期。

小的日期自增到与大的日期相等,自增的次数就是两个日期相差的天数。加一个flag标志用来区分日期相差的正负。

<<流插入运算符重载。我们知道流插入运算符可以打印基本数据类型。用户自定义的类型,能不能使用系统自带的流插入运算符呢?是不行的,需要我们进行函数名重载,便于支持自定义类型的打印。

ostream& operator<<(ostream& out,const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}

流插入运算符的重载函数。不能作为类的成员函数,因为成员函数的第一个参数默认是类的this指针。但是我们使用流插入运算符是cout<<d<<endl;第一个参数为cout,所以我们不能使用成员函数作为重载函数,那么我们类外不能访问私有成员。该怎么办?我们将函数声明为友元函数,友元函数可以在类外访问私有成员。

在类内加入

为什么返回类型为ostream呢,因为这样可以做到连续的流插入,输出多个结果。

流提取运算符重载函数

我们知道>>可以输入基本的数据类型。但是日期类是我们自定义的类型。我们使用>>输入就需要对>>进行运算符重载。

与流插入运算符的重载函数一样。流提取运算符重载函数,也不能使用成员函数。写在类外将这个函数作为类的友元函数。

istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}

在类内声明:

对<<、>>进行了运算符重载。我们就可以直接使用其操作了。

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

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

相关文章

django rest_framework 部署doc文档

1.背景 在实际开发过程中&#xff0c;前后端分离的项目&#xff0c;是需要将一份完整的接口文档交付给前端开发人员&#xff0c;这样有利于开发速度和开发质量&#xff0c;以及有可能减少协同时间。 2.内容 本项目是以Pythondjangorest_framework作为技术框架&#xff0c;在这…

设计模式之里氏代换原则:打破常规,让代码更灵活

在软件开发的世界中&#xff0c;设计模式是解决常见问题的最佳实践。其中&#xff0c;里氏代换原则&#xff08;Liskov Substitution Principle&#xff0c;LSP&#xff09;是面向对象设计的基本原则之一&#xff0c;它强调了在软件中子类型必须能够替换其基类型&#xff0c;而…

Zabbix监控(2)

目录 一.自动发现 配置自动发现&#xff1a;&#xff08;被动模式&#xff09; 修改三台服务器的hosts文件&#xff1a; 修改agent02的配置文件&#xff1a; 访问页面&#xff0c;删除客服端主机配置&#xff1a; 在配置的自动发现中添加规则&#xff1a; 我们重启的zab…

基于springboot的疫情物资捐赠和分配系统

&#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;一 、设计说明 1.1 课题背景 二…

网站引导页源码带视频背景源码系统:HTML5开发的引导页 附带完整的搭建教程

随着互联网技术的飞速发展&#xff0c;网站引导页作为用户体验的重要环节&#xff0c;越来越受到开发者的关注。传统的静态图片引导页已经无法满足用户对于新鲜感和互动性的需求。小编给大家分享一款基于HTML5的带视频背景的源码系统&#xff0c;旨在为用户提供更加丰富、动态的…

细说JavaScript内置对象(JavaScript内置对象详解)

一、String对象 1、简单上手 2、构造方法 3、其他方法 3.1、charAt() 3.2、indexOf() 3.3、split() 3.4、substring() 3.5、substr() 4、实际操作 二、Math对象 1、简单上手 2、对象属性 3、对象方法 4、实际操作 三、Date对象 1、简单上手 2、构造方法 3、实…

【网络安全】【密码学】【北京航空航天大学】实验四、古典密码(上)【C语言实现】

实验四、古典密码&#xff08;上&#xff09; 一、实验目的 1、 通过本次实验&#xff0c;了解古典加密算法的主要思想&#xff0c;掌握常见的古典密码。 2、 学会应用古典密码&#xff0c;掌握针对部分古典密码的破译方法。 二、原理简介 古典密码的编码方法主要有两种&am…

第一个 OpenGL 程序:旋转的立方体(VS2022 / MFC)

文章目录 OpenGL API开发环境在 MFC 中使用 OpenGL初始化 OpenGL绘制图形重置视口大小 创建 MFC 对话框项目添加 OpenGL 头文件和库文件初始化 OpenGL画一个正方形OpenGL 坐标系改变默认颜色 重置视口大小绘制立方体使用箭头按键旋转立方体深度测试添加纹理应用纹理换一个纹理 …

【电商API接口】挖掘电商数据常用的方法

电子商务模式是一个连接线上用户和线下商家的多边平台商业模式。O2O 商业模式将实体经济与线上资源融合在一起&#xff0c;使网络成为实体经济延伸到虚拟世界的渠道; 线下商业可以到线上挖掘和吸引客源&#xff0c;而消费者可以在线上筛选商品和服务并完成支付&#xff0c;再到…

CMake 实战构建TcpServer项目 静态库/动态库

爱编程的大丙CMake&#xff1a; 20. 举例 - 下_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV14s4y1g7Zj?p20&spm_id_frompageDriver&vd_sourcea934d7fc6f47698a29dac90a922ba5a3 hehedalinux:~/Linux/LinuxServerCpp$ ls Buffer.cpp Log.h Buffe…

基于Java SSM框架实现学生综合考评管理系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现学生学生综合考评管理系统演示 摘要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 学生综合考评管理系统&#xff0c;主要的模块包括查看&#xff1b;管理员&#xff1b;个…

知识分享:一文读懂AIGC与大模型

什么是大模型&#xff1f; 关于大模型&#xff0c;有学者称之为“大规模预训练模型”(large pretrained language model&#xff09;&#xff0c;也有学者进一步提出”基础模型”(Foundation Models)的概念。 “小模型”&#xff1a;针对特定应用场景需求进行训练&a…

音频文件格式–celt

CELT介绍 CELT 是一种开放、免版税的有损音频压缩格式&#xff0c;也是一种免费软件编解码器&#xff0c;具有特别低的算法延迟&#xff0c;适用于低延迟音频通信。这些算法是公开记录的&#xff0c;并且可以不受软件专利限制地使用。 CELT 是一种基于改进的离散余弦变换 (MD…

你还没脱单,这些软件都得背锅

不管你是否认可情人节概念&#xff0c;是否会在这天与自己的那个ta相聚&#xff0c;每个成年人都会或多或少地思考自己的感情问题。 在互联网兴盛之前&#xff0c;人与人的交往大都依靠职场关系和熟人介绍来结识新的对象&#xff0c;但也有媒人、婚姻介绍所等专门的职业为适龄…

基于Jackson自定义json数据的对象转换器

1、问题说明 后端数据表定义的id主键是Long类型&#xff0c;一共有20多位。 前端在接收到后端返回的json数据时&#xff0c;Long类型会默认当做数值类型进行处理。但前端处理20多位的数值会造成精度丢失&#xff0c;于是导致前端查询数据出现问题。 测试前端Long类型的代码 …

安卓接入google的Firebase登录教程

1.https://console.firebase.google.com创建安卓项目 2.添加google登录 3.添加项目的SHA证书指纹 4. FireBase自动生成&#xff08;API和服务&#xff09; https://console.cloud.google.com/apis/credentials?authuser1&projectbattle-against-darkness 5.下载goog…

3.3.2 CSMA/ CD协议

3.3.2 CSMA/ CD协议 CSMA/CD&#xff08;Carrier Sense Multiple Access with Collision Detection&#xff09;&#xff1a;载波监听多点接入/碰撞检测。 检测到碰撞后&#xff1a; 适配器立即停止发送。&#xff08;碰撞点后面的信号会一直叠加&#xff09;等待一段随机时间…

使用cURL和wget在Linux上进行HTTP请求和下载

在Linux上&#xff0c;cURL和wget是两个常用的命令行工具&#xff0c;用于发送HTTP请求和下载文件。下面我将详细介绍如何使用这两个工具进行HTTP请求和下载操作。 首先&#xff0c;让我们了解一下cURL。cURL是一个功能强大的命令行工具&#xff0c;可以用来发送各种类型的HTT…

WinEdt运行latex文件有eps图片编译不通过,各种报错解决办法

一、背景 我们在使用Winedt编辑并且编译Latex文件时&#xff0c;一般会选择PDFTeXify格式一键编译和生成pdf&#xff0c;如下图所示的选项&#xff0c;这样确实很方便&#xff0c;但经常会出现bug&#xff0c;例如转圈卡死&#xff0c;或编译不通过&#xff0c;报错Unknown gr…

【翻译】在Qt Designer中创建主窗口(Main Windows)

原文地址&#xff1a;https://doc.qt.io/qt-6/designer-creating-mainwindows.html Qt Designer 可用于为不同用途创建用户界面&#xff0c;并为每个用户界面提供不同类型的模板。主窗口模板用于创建具有菜单栏、工具栏和停靠窗口部件的应用程序窗口。 通过打开文件菜单并选择…