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

【C++】运算符重载(日期类的实现)

【C++】运算符重载(日期类的实现)

  • 前言
  • 运算符重载
    • operator
      • 全局和类中
  • 日期类的实现
    • 成员变量的确定
    • 构造函数
      • 拷贝构造
    • 运算符重载部分
      • +=的重载
        • 思路
        • 实现
          • GETmonthday
          • operator+=
      • +的重载
        • 思路
        • 实现
      • -=的与-的重载
        • 实现
      • 各个比较运算符的重载
        • 实现
      • 前置++与后置++
        • 实现
      • (=)赋值运算符的重载
        • 实现
  • 后话

前言

博主在快写完类和对象(中)时,突然发现需要用到运算符重载的知识
但是运算符有很多运算符要进行重载,会导致文章的篇幅略长
所以就单独写了一个,另外,日期类是学习运算符重载比较好的一个例子,所以这里就用了日期类来讲解运算符重载

运算符重载

众所周知,对于内置类型我们可以直接使用运算符进行计算
int y=1, int x=1 x+y
这显然是可以的

那自定义类型可不可以直接用运算符来算呢?
比如
stack s1; stack s2; s1+s2

当然是不可以的

这不是显而易见吗
现在编译器也不至于聪明到能直接分辨出用户的自定义类型的运算。
要是编译器真的高级到这个程度,那就是更高级的语言了

但是类如果要进行加减乘除的时候又要进行函数的调用

如果能直接用加减乘除等操作符的话,那不是能大大增强函数的可读性吗?

所以就有了关键字

operator

运算符重载函数的形式为:
void(返回类型)operator<(需要重载的运算符)(参数)
例:

Date& operator+=(int x);

这里在使用operator进行重载时
有几个点需要注意:

1.不可以用operator重载一个原本没有意义的符号。

如:operator@

2.运算符重载必须有一个自定义类型的对象

因为本来运算符重置就是为了自定义类而创建
要是没有自定义类的对象参数
那还有啥意义。

在这里插入图片描述

这五个运算符不能进行重载。

4.讲了很多次
自定义类型深究到最后,也就只是内置类型

所以当我们编写运算符重载函数的时候:
内置类型的运算符含义不能进行改变

你想改也改不了。

全局和类中

这里来给大家提个问题,全局和类,有啥区别

1. 全局中的函数无法随意调用类中的私人成员

在这里插入图片描述
就会出现这样尴尬的场面(这里有解决方法,但是还是留在之后讲)

但是如果将运算符重载函数写在类中,就可以随意调用了。

2. 类中有this指针这个存在

这意味着运算符重载在全局和类中有不同的定义方式

上面我们看到了:

全局对象需要完全地写出参数

但是在类中的函数因为有this指针的隐形传参,所以不需要将全部参数写出来

class Date
{Date& operator+=(int day) {}
}

这里this指针将对象的地址传了过去

所以不需要像全局变量一样传一个类的对象形参

所以为了方便,还是尽量讲运算符重载函数写在类中。

日期类的实现

日期算是我们生活中常见的了。

成员变量的确定


年-月-日组成

所以我们这里针对成员变量的设计也是十分容易

class Date
{
private:int _year;int _month;int _day;
};

构造函数

还记得我们这里要创建构造函数的原因吗?

因为date类中全是内置类型
编译器自动生成的默认构造函数不会对内置类型变量进行设定。
所以遇到内置类型就要自己写构造函数了

这里就写个缺省的和无参的

//缺省Date(int year,int month,int day){_year = year;_month = month;_day = day;}//无参
Date()
{_year = 2023;_month = 5;_day = 24;
}

拷贝构造

因为拷贝构造属于构造函数里的,这里就直接把它放在这里了

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

运算符重载部分

这个部分算是正式进入我们的正题了

这里的函数我都默认放在类中进行实现的。

+=的重载

这里要实现的功能是:

日期+=天数 =>(返回)新日期

注意这个运算符号是+=,原本就是要对前一个值进行改变的。
所以我们这里就是对 原对象进行+=,然后返回原对象就好

这里理解起来很容易,但是要实现起来的话还是有点小繁琐的。

思路

想要得到日期+天数转化为日期。

1.首先要得到知道每个月的天数

2.将现在日期的天数和传参的天数相加

3.判断,现在天数是否大于这个月应有的天数

若大于:
扣除每个月对应的天数,然后月份+1

若小于:
则日期已经++完成,直接返回就好

实现

我们要知道所在的这个月的天数,所以我们需要设定一个函数专门用来返回当月的对应的天数

GETmonthday
int GETmonthday(int year, int month)
{static int arr[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 29;}return arr[month];
}

这里通过静态数组将每个月对应的天数存储下来
(因为这个函数在后续需要多次调用,所以使用静态数组,防止多次开辟空间影响效率)

通过传来的年月,来进行 闰年/平年 对应月 的判断
得到对应的天数后返回。

operator+=
//这里返回值用了引用,因为+=返回的就是原对象,函数结束后没有随着函数被销毁。
Date& operator+=(int day) 
{_day += day;//将天数和天数相加while (_day > this->GETmonthday(_year,_month))//当现有天数大于本月总天数,程序继续{_day -= GETmonthday(_year, _month);_month++;//天数减去这个月对应天数,当前月份++if (_month > 12)//当月份大于12时,年++,当前月份变为1{_month = 1;_year++;}}return *this;//返回改变后的天数
}

+的重载

思路

+和+=有啥区别?

+=对原对象进行了改变,并且返回的也是原对象

而+ 就不一样了:
不会对原对象进行赋值改变
并且返回的是:原对象与天数相加后的新对象

实现

这里搞懂了区别后就可以进行实现了

这里就会发现:
其实+=和+中间的对象与天数相加的思路一样
就是需要
1.返回新对象
2.原对象不能进行改变。

Date operator+(int day)
{
//用原对象进行了拷贝构造出了tmpDate tmp(*this);//将tmp进行+=(用的是之前实现的+=重载)tmp += day;
//返回tmpreturn tmp;
}

-=的与-的重载

这里其实思路和+=与+的重载相似,所以这里就不多讲了
因为这篇博客主要是想讲清不同运算符重载的实现

实现

//-=的实现
Date& operator-=(int day)
{_day -= day;while (_day <= 0){_day += GETmonthday(_year, _month);_month--;if (_month < 1){_month = 12;_year--;}}return *this;
}
}
//-的实现
Date operator-(int day)
{Date tmp(*this);tmp -= day;return tmp;
}

各个比较运算符的重载

这里比较运算符算是最简单的运算符重载了

传入一个Date类对象
和this指针的本对象进行年月日比较
最后返回布尔值即可

实现

//<的实现
bool operator<(const Date& d)
{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 operator>(const Date& d)
{return ((!(*this < d)) && (!(*this == d )));
}//等于的实现
bool operator==(const Date& d)
{return _day == d._day && _year == d._year && _month == d._month;
}
//大于等于的实现
bool operator>=(const Date& d)
{return !(*this < d);
}
//小于等于的实现
bool operator<=(const Date& d)
{return !(*this > d);
}
//不等于的是实现
bool operator!=(const Date& d)
{return !(*this == d);}

前置++与后置++

这里还是和之前一样,来搞清楚这两个的区别

前置++

直接对象+1,然后返回对象值即可

后置++
先返回对象的原值,然后对象值++
这里的实现思路肯定不是这样,return值了以后函数就结束,怎么还能++

所以这里就要用原对象创建新对象
对原对象++,返回创建的新对象

搞清楚思路了以后,接下来还有个问题

区分两者

还记的运算符重载的命名方式吗

void(返回类型)operator<(需要重载的运算符)(参数)

但是前置++和后置++,都是++运算符

所以定义时都是operator++

这就不好区分了

但是祖师爷在定义的时候就发现

自增运算符都是对单个对象的运算

所以传参时不需要传任何参数
(原对象this指针会进行传递)

那让编译器给前置运算符或者前置运算符
随便传一个参数不就可以识别了吗

所以选择了后置++

Date& Date::operator++()
//前置++
Date Date::operator++(int)
//后置++
//用户自己声明时,要在后置运算符加上int参数

实现

//前置++
Date& Date::operator++()
{return (*this += 1);
}//后置++
Date Date::operator++(int)
{Date tmp(*this);*this += 1;return tmp;
}

所以从上面的实现中可以看出

当我们用自定义类型的++时,最好使用前置++

因为后置++需要创建一个新对象,会影响效率。

同样对于内置类型前置++和后置++

虽然也大致是这样的原理
前置++比后置++更加有效率
但是因为内置类型拷贝成本比较低
所以没有特意去区分前置++和后置++的使用

(=)赋值运算符的重载

我们知道,赋值运算符也是默认成员函数之一
就是用户不写时,编译器会自己生成。

目的:将一个对象的值,赋值给另一个对象

实现

在这里插入图片描述

这个赋值构造函数可能看着没啥问题

但是别忘了,对于内置类型来说,赋值能这样做

x=y=c=a
能做到这样的连续赋值。

但是我们的这个实现方法不能进行连续赋值

原因就在于:
返回类型为空

所以这里需要把赋值后的原对象进行返回

Date& operator=(Date& d1)
{_year = d1._year;_day = d1._day;_month = d1._month;return (*this);
}

后话

这里其实还有很多内容没有去实现。

比如说
对象与对象的运算符
后置–与前置–
但是这里主要是想带大家学习一下重载运算符而已,
所以这个日期类就点到为止。

相关文章:

【C++】运算符重载(日期类的实现)

【C】运算符重载&#xff08;日期类的实现&#xff09; 前言运算符重载operator全局和类中 日期类的实现成员变量的确定构造函数拷贝构造 运算符重载部分的重载思路实现GETmonthdayoperator 的重载思路实现 -的与-的重载实现 各个比较运算符的重载实现 前置与后置实现 &#xf…...

【Linux】线程分离 | 线程库 | C++调用线程 | 线程局部存储

文章目录 1. 线程分离1. 为什么要线程分离&#xff1f;2. 具体使用3. 为什么有时候分离在调用join 会正常运行&#xff1f; 2. 如何理解线程库&#xff1f;如何理解 先描述 在组织&#xff1f; 3. C中使用多线程4. 线程局部存储局部变量全局变量 1. 线程分离 1. 为什么要线程分…...

c++ ffmpeg 浅谈YUV444、YUV422、YUV420(2)

本期将会给大家介绍YUV相关基础知识&#xff0c;同时也介绍威创网络分布式系统的卓越色彩处理技术。 1.什么是YUV色彩空间 2.YUV采样格式 3.YUV不同采样格式对图像画质的影响分析 一、什么是YUV色彩空间? YUV是视频、图片、相机等应用中常常使用的一类图像格式&#xff0c;是…...

Redis在Windows下安装配置教程

Redis是一个开源的高性能键值对存储数据库&#xff0c;常用于缓存、消息队列等场景。本文将介绍如何在Windows系统下安装配置Redis。 1. 下载地址 Redis官方网站提供了Windows版本的安装包下载地址&#xff0c;网址为&#xff1a;https://github.com/tporadowski/redis/relea…...

数据库服务器

数据库服务器&#xff0c;联系Web服务器与DBMS的中间件是负责处理所有的应用程序服务器&#xff0c;包括在web服务器和后台的应用程序或数据库之间的事务处理和数据访问。 基本信息 中文名 数据库服务器 外文名 database server 功能 数据库服务器建立在数据库系统基础上&a…...

VS输出路径和生成事件

在生成时&#xff0c;常常希望输出文件夹整洁&#xff0c;因此需要设置dll或exe输出位置&#xff0c;同时也希望对一些文件做一些特殊操作 VS的 UI 常用缩写 “./”&#xff1a;代表目前所在的目录。 " . ./"代表上一层目录。 “/”&#xff1a;代表根目录。 生成…...

从 WebKit 看浏览器内核架构

浏览器常见的浏览器内核有&#xff1a;Blink、WebKit、Gecko、Trident 等&#xff0c;目前 WebKit 内核占据了非常大的的市场&#xff0c;包括 Chrome、Safari、安卓浏览器等市面上的主流浏览器&#xff0c;都使用了 WebKit 内核。 从 WebKit 看浏览器内核架构 既然 WebKit 这么…...

使用原生的 JavaScript,不依赖于任何特定的库与 ROSBridge进行通信

使用原生的 JavaScript&#xff0c;不依赖于任何特定的库与 ROSBridge进行通信 创建与 ROS 的连接&#xff1a; var rosbridge_url "ws://localhost:9090"; var ws new WebSocket(rosbridge_url);ws.onopen function(event) {console.log(Connected to rosbri…...

MATLAB第十章_图像处理算法

目录 图像处理算法 图像处理基础 图像处理函数 默认显示方式 添加颜色条 显示多帧图像 显示动画 三维材质图像 图像的直方图 灰度变换 均衡直方图 图像处理应用 图像增强 图像重建 图像变换 图像压缩 图像分割 图像边缘检测 图像识别 图像处理算法 图像处理…...

RobotFramework接口测试方案

1. Robot FrameWork介绍 1.1 介绍 Robot Framework是用于验收测试和回归测试的通用测试自动化框架。它使用易于理解的表格数据语法&#xff0c;非常友好的实现了关键字驱动和数据驱动模式。它的测试功能可以通过使用Python或Java实现的测试库进行扩展&#xff0c;用户可以使用…...

chatgpt赋能python:Python中日期转换:从字符串到日期对象

Python中日期转换&#xff1a;从字符串到日期对象 作为一个经验丰富的Python工程师&#xff0c;日期转换在我的日常编码工作中经常遇到。Python提供了一些内置函数和模块&#xff0c;可以将字符串转换为日期对象或将日期对象格式化为特定的字符串。本篇文章将带您深入了解Pyth…...

k8s 1.27新特性in-place使用方法:避坑指南(官方文档有坑,已提issue)

背景 按照官方文档试用新版的in-place特性时&#xff0c;一字不差地执行了&#xff0c;但是却出现了执行失败的情况&#xff1a; 执行kubectl -n qos-example patch pod qos-demo-5 --patch {"spec":{"containers":[{"name":"qos-demo-ct…...

网络传输(传输介质、通信方式、交换方式)

目录 一、传输介质1.双绞线2.网线安装3.光纤4.无线信道 二、通信方式、交换方式1.通信方式2.同步方式3.交换方式 一、传输介质 1.双绞线 双绞线&#xff1a;将多根铜线按规则缠绕在一起&#xff0c;能够减少干扰&#xff1b;分为无屏蔽双绞线UTP和屏蔽双绞线STP&#xff0c;都…...

【Unity】Time.deltaTime有什么用?看完你就明白

大多数刚开始使用 Unity 的人(包括我),都会对Time.deltaTime感到迷惑。 看完本文,你就会明白Time.deltaTime的定义及作用。 1、deltaTime是什么? 根据定义,Time.deltaTime是每一帧之间的时间间隔(以秒为单位)。 这有助于我们使游戏与帧数无关,也就是说,无论 fps 是…...

vue实现用户动态权限登录

一、使用vueelementUI搭登录框架&#xff0c;主要就是1、2、3、4 配置&#xff1a; ①vue.config.js use strict const path require(path)function resolve(dir) {return path.join(__dirname, dir) }// All configuration item explanations can be find in https://cli.v…...

ONNX模型修改为自定义节点

参考一 首先&#xff0c;需要将ONNX模型中的节点修改为自定义节点。要实现这一点&#xff0c;您需要了解自定义节点的定义和如何在ONNX中使用它们。ONNX定义了一个自定义运算符的接口&#xff0c;您可以使用该接口定义自己的运算符&#xff0c;并将其编译为ONNX模型可以识别的…...

内存对齐原则

struct &#xff08;1&#xff09;结构体第一个数据成员放在offset为0的地方&#xff0c;后面每个成员相对于结构体首地址的偏移量&#xff08;offset&#xff09;都是成员大小&#xff08;该变量类型所占字节&#xff09;的整数倍&#xff0c;如有需要编译器会在成员之间加上填…...

Java SPI 一 之SPI(Service Provider Interface)进阶 AutoService

​ 一、SPI&#xff08;Service Provider Interface&#xff09; 1.1 介绍 SPI&#xff08;Service Provider Interface&#xff09;&#xff0c;是JDK内置的一种 服务提供发现机制(为某个接口寻找服务实现的机制)&#xff0c;可以用来启用框架扩展和替换组件&#xff0c;其…...

C++ list类成员函数介绍

目录 &#x1f914;list模板介绍&#xff1a; &#x1f914;特点&#xff1a; &#x1f914;list内存结构图解&#xff1a; &#x1f914; list的成员函数&#xff1a; &#x1f60a;list构造函数&#xff1a; &#x1f50d;代码示例&#xff1a; &#x1f50d;运行结果&…...

【服务器】本地搭建PHP简单Imagewheel私人云图床

文章目录 1.前言2. Imagewheel网站搭建2.1. Imagewheel下载和安装2.2. Imagewheel网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar临时数据隧道3.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测…...

如何通过抖音批量下载工具实现高效内容管理与分析

如何通过抖音批量下载工具实现高效内容管理与分析 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. 抖音批量下载…...

NaViL-9B开源模型GPU适配详解:eager注意力回退机制原理与影响

NaViL-9B开源模型GPU适配详解&#xff1a;eager注意力回退机制原理与影响 1. 模型概述与技术背景 NaViL-9B是由国内顶尖研究机构发布的开源多模态大语言模型&#xff0c;具备同时处理文本和图像输入的能力。作为原生多模态架构的代表&#xff0c;该模型在9B参数规模下实现了高…...

别再用PS硬P了!用Python+OpenCV实现泊松融合,5分钟搞定图片无缝拼接

告别PS繁琐操作&#xff1a;5行Python代码实现专业级图片融合 每次在Photoshop里手动调整图层蒙版、反复擦除边缘时&#xff0c;你是否想过——数字图像处理应该更智能&#xff1f;2023年&#xff0c;我们完全可以用代码自动化完成这些重复劳动。本文将带你用PythonOpenCV实现泊…...

Chord视觉定位模型实战案例:自动驾驶道路元素(车道线/交通灯/行人)定位

Chord视觉定位模型实战案例&#xff1a;自动驾驶道路元素&#xff08;车道线/交通灯/行人&#xff09;定位 在真实自动驾驶场景中&#xff0c;单纯依赖传统目标检测模型往往面临泛化能力弱、小目标漏检、遮挡鲁棒性差等问题。而Chord——这个基于Qwen2.5-VL的多模态视觉定位服…...

Cesium实战:5分钟搞定飞机轨迹飞行与流光道路效果(附完整代码)

Cesium实战&#xff1a;5分钟实现飞机轨迹飞行与流光道路特效 第一次接触Cesium时&#xff0c;我就被它强大的三维地理可视化能力震撼了。作为一个长期从事WebGIS开发的工程师&#xff0c;我一直在寻找能够快速实现复杂三维场景的工具。直到遇到Cesium.js&#xff0c;才发现原来…...

Elasticsearch-PHP异步搜索终极指南:如何实现高性能搜索应用

Elasticsearch-PHP异步搜索终极指南&#xff1a;如何实现高性能搜索应用 【免费下载链接】elasticsearch-php Official PHP client for Elasticsearch. 项目地址: https://gitcode.com/gh_mirrors/el/elasticsearch-php Elasticsearch-PHP是官方PHP客户端&#xff0c;为…...

Android混淆配置终极指南:基于Awesome Android库的完整ProGuard规则

Android混淆配置终极指南&#xff1a;基于Awesome Android库的完整ProGuard规则 【免费下载链接】awesome-android A curated list of awesome Android packages and resources. 项目地址: https://gitcode.com/gh_mirrors/awe/awesome-android 在Android应用开发中&…...

ArduinoEigen:嵌入式平台轻量级Eigen线性代数库移植

1. ArduinoEigen&#xff1a;面向嵌入式平台的轻量化Eigen线性代数库移植1.1 项目定位与工程价值ArduinoEigen 是一个专为资源受限嵌入式平台定制的 Eigen 线性代数库移植版本&#xff0c;其核心目标并非简单地将桌面级 C 数值计算库“搬上”MCU&#xff0c;而是通过深度裁剪、…...

Diablo Edit2实战解决方案:从存档修复到角色定制的完整指南

Diablo Edit2实战解决方案&#xff1a;从存档修复到角色定制的完整指南 【免费下载链接】diablo_edit Diablo II Character editor. 项目地址: https://gitcode.com/gh_mirrors/di/diablo_edit 在暗黑破坏神II的冒险旅程中&#xff0c;每位玩家都可能遭遇存档损坏、属性…...

终极指南:免费解锁Cursor Pro完整功能,告别AI编程限制

终极指南&#xff1a;免费解锁Cursor Pro完整功能&#xff0c;告别AI编程限制 【免费下载链接】cursor-free-vip [Support 0.45]&#xff08;Multi Language 多语言&#xff09;自动注册 Cursor Ai &#xff0c;自动重置机器ID &#xff0c; 免费升级使用Pro 功能: Youve reach…...