C++运算符重载实现日期类

news2025/1/11 22:44:50

目录

     

运算符重载 

日期类头文件time.h

time.h

日期类成员函数文件time.cpp

        1.GetMonthDay函数

        2.构造函数Date::Date(int year, int month, int day)

        3.赋值函数Date& operator=(const Date& d)

        4.Date& Date::operator+=(int day)函数实现日期加天数的功能

        5.前置++和后置++

test.cpp


     

运算符重载 

       运算符重载是具有特殊函数名的函数,也具有其 返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
        函数名字为:关键字 operator后接需要重载的运算符符号
        函数原型: 返回值类型operator操作符(参数列表)
        例如:
Date operator=(const Date& d)

注意:

  • 不能通过连接其他符号来创建新的操作符:比如operator@
  • 重载操作符必须有一个类类型参数
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义
  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏参数this
  • .*    ::      sizeof      ?:     .  这五个运算符不能重载

日期类头文件time.h

time.h

日期类头文件包含头文件,类的定义,成员函数和成员变量的声明。代码如下:

#pragma once
#include<iostream>
using namespace std;

class Date
{
public:
	Date(int year, int month, int day);//日期类构造函数
	void Print(); //打印
	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);
	
	Date& operator=(const Date& d);
	Date& operator+=(int day);
	Date operator+(int day);
	Date& operator-=(int day);

	//d1-100
	Date operator-(int day);          //日期减去天数

	//d1-d2
	int operator-(const Date& d);     //日期减去日期,一般没有意义

	//++d1
	Date& operator++();               //前置++,返回的是++之后的值

	//d1++
	//int参数 仅仅是为了占位,跟前置重载区分
	Date operator++(int);             //后置++,先返回d1的值,再++
private:
	int _year;                        //年
	int _month;                       //月
	int _day;                         //日
};

以上代码中成员变量包含年月日,d1表示日期类实例,d2也是。

日期类成员函数文件time.cpp

成员函数包括日期类成员函数的定义:

#include"time.h"

	int Date::GetMonthDay(int year, int month)
	{
		static int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		int day = days[month];
		if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
		{
			day += 1;
			return day;
		}
		else
		{
			return day;
		}
	}

	Date::Date(int year, int month, int day)
	{
		if (month > 0 && month < 13 && (day > 0 && day <= GetMonthDay(year, month)))
		{
			_year = year;
			_month = month;
			_day = day;
		}
}
	void Date::Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}

	//d1==d2
	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);
	}

	//d1<d2
	bool Date::operator<(const Date& d)
	{
		return _year < d._year 
			|| (_year == d._year && _month < d._month) 
			|| (_year == d._year && _month == d._month && _day < d._day);
	}

	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);
	}

	//返回值为了支持连续赋值,保持运算符的特性
	//d3=d2=d1;
	//d1=d1
	Date& Date::operator=(const Date& d)
	{
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}

	Date& Date::operator+=(int day)
	{
		_day += day;
		while (_day > GetMonthDay(_year, _month))
		{
			_day -= GetMonthDay(_year, _month);
			_month++;
			if (_month > 13)
			{
				++_year;
				_month = 1;
			}
		}
		return *this;
	}

	//Date Date::operator+(int day)
	//{
	//	Date tmp(*this);
	//	tmp._day += day;
	//	while (tmp._day > GetMonthDay(tmp._year, tmp._month))
	//	{
	//		tmp._day -= GetMonthDay(tmp._year, tmp._month);
	//		++tmp._month;
	//		if (tmp._month == 13)
	//		{
	//			++tmp._year;
	//			tmp._month = 1;
	//		}
	//	}
	//	return tmp;
	//}
	Date Date::operator+(int day)
	{
		Date tmp(*this);
		tmp += day;
		return tmp;
	}

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

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

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

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

        1.GetMonthDay函数

输入参数year和参数month,输出year和month对应的day。实现逻辑是先定义一个数组存放12个月每个月的天数,因为月份是从1月开始数的,而数组有days[0],所以给数组赋值时,days[0]=0;还有一个是闰年的计算,闰年的2月天数是28天,非闰年2月是29天。闰年2月天数的计算逻辑,如果月份是2月并且年份能整除4但是不能整除100或者年份能整除400

if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
		{
			day += 1;
			return day;
		}
		else
		{
			return day;
		}

        2.构造函数Date::Date(int year, int month, int day)

这里需要注意的是非法日期的检查,不可以输入一个不合理的日期,比如月份大于13或者月份小于0.月份和天数都要合理

if (month > 0 && month < 13 && (day > 0 && day <= GetMonthDay(year, month)))

        3.赋值函数Date& operator=(const Date& d)

返回值为了支持连续赋值,保持运算符的特性,检查日期是否给自己赋值。

ef73f62d137c4793a9978082fec79c68.png

赋值运算符"=",是先将d3赋值给d2,再将d2赋值给d1,最后返回d1的值,从右往左赋值。

        4.Date& Date::operator+=(int day)函数实现日期加天数的功能

实现逻辑是先加上天数,判断天数是否大于当月天数,如果大于则进入while循环,先减去当月天数,月份加1,返回*this.

75fd0f559c464444bf2b6a0091cbd8cd.png

        5.前置++和后置++

前置++是返回++之后的值,后置++先返回值,再++

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

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

tmp是*this的拷贝构造,因为后置++是先返回值才++,所以需要一个日期类的副本去保存它。

test.cpp


#include"time.h"

void TestDate1()
{
	Date d1(2023, 2, 4);
	Date d2(2023, 3, 4);
	d1.Print();
	d2.Print();
	cout << d1.operator==(d2) << endl;
	cout << (d1 == d2) << endl;//转换成去调用这个d1.operator==(d2);
	cout << (d1 < d2) << endl;
}

void TestDate2()
{
	Date d1(2023, 5, 6);
	Date d2 = d1;
	d2 += 1500;
	d1.Print();
	d2.Print();
	Date d3 = d2 + 100;
	d3.Print();
}

void TestDate3()
{
	Date d1(2023, 5, 7);
	d1.Print();

	d1 -= 100;
	d1.Print();
}
int main()
{
	TestDate3();
	return 0;
}

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

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

相关文章

用编程思想解决问题

1.是什么 分解法&#xff1a;将复杂的问题分解为一个个小又容易的问题&#xff0c;再逐一解决 先常后变&#xff1a;先使用常量来解决问题后使用变量来代替常量&#xff0c;使代码变得更灵活 例题一&#xff1a; 请你使用Switch分支结构根据输入的分数来定成绩所在区间&…

若依 ruoyi-vue 获取上一页路由 获取返回上一页路径 登录后跳转其他页面 登录进入后跳转至动态路由的第一个路由

参考文章:若依框架登录后跳转其他页面&获取不同的菜单&登录进入后跳转至动态路由的第一个路由 需求&#xff1a;登录成功&#xff0c;默认跳转至后端返回的动态路由的第一个路由 src/store/modules/permission.js 将动态路由的第一个路由存到缓存中 import cache …

多人开发小程序设置体验版的痛点

抛出痛点 在分配任务时,我们将需求分为三个分支任务,分别由前端A、B、C负责: 前端A: HCC-111-实现登录功能前端B: HCC-112-实现用户注册前端C: HCC-113-实现用户删除 相应地,我们创建三个功能分支: feature_HCC-111-实现登录功能feature_HCC-112-实现用户注册feature_HCC-1…

新手向教学,分分钟搭建个人定制化的 ChatgptGPT 聊天机器人

对话机器人变得越来越流行&#xff0c;它为用户提供了与技术互动的方式。OpenAI 的“GPT”模型让开发者能够创建复杂的对话机器人。 在本教程中&#xff0c;我们将使用 Python 和 OpenAI API 在运行 Ubuntu 的 DigitalOcean Droplet 上构建并部署你自己的终端 ChatGPT 机器人。…

基于SpringBoot+Vue+MySQL的校园食堂订餐

系统展示 用户前台界面 管理员后台界面 系统背景 随着信息技术的飞速发展和互联网的普及&#xff0c;传统校园食堂的运作模式已难以满足现代学生日益增长的便捷性、个性化需求。学生们希望能够在忙碌的学习生活中&#xff0c;通过更加高效、便捷的方式完成就餐选择&#xff0c;…

【算法篇】数组类(笔记)

目录 一、二分查找 1. 方法一 2. 方法二 二、移除元素 1. 暴力破解 2. 双指针法 三、有序数组的平方 双指针法 四、长度最小的子数组 1. 暴力破解 2. 滑动窗口 五、螺旋矩阵 II 一、二分查找 704. 二分查找 - 力扣&#xff08;LeetCode&#xff09;https://leet…

深入理解Java虚拟机:Jvm总结-虚拟机字节码执行引擎

第八章 虚拟机字节码执行引擎 8.1 意义 不受物理条件制约地定制指令集与执行引擎的结构体系&#xff0c;能够执行那些不被硬件直接支持的指令集格式。输入的是字节码二进制流&#xff0c;处理过程是字节码解析执行的等效过程&#xff0c;输出的是执行结果 8.2 运行时栈帧结构…

jupyter出错ImportError: cannot import name ‘np_utils‘ from ‘keras.utils‘ ,怎么解决?

文章前言 此篇文章主要是记录一下我遇到的问题以及我是如何解决的&#xff0c;希望下次遇到类似问题可以很快解决。此外&#xff0c;也希望能帮助到大家。 遇到的问题 出错&#xff1a;ImportError: cannot import name np_utils from keras.utils &#xff0c;如图&#xf…

Metasploit Pro 4.22.3-2024081901 (Linux, Windows) - 专业渗透测试框架

Metasploit Pro 4.22.3-2024081901 (Linux, Windows) - 专业渗透测试框架 Rapid7 Penetration testing, release Aug 19, 2024 请访问原文链接&#xff1a;https://sysin.org/blog/metasploit-pro-4/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页…

SonicWall SSL VPN曝出高危漏洞,可能导致防火墙崩溃

近日&#xff0c;有黑客利用 SonicWall SonicOS 防火墙设备中的一个关键安全漏洞入侵受害者的网络。 这个不当访问控制漏洞被追踪为 CVE-2024-40766&#xff0c;影响到第 5 代、第 6 代和第 7 代防火墙。SonicWall于8月22日对其进行了修补&#xff0c;并警告称其只影响防火墙的…

代码随想录27期|Python|Day51|​动态规划|​115.不同的子序列|​583. 两个字符串的删除操作​|72. 编辑距离

115. 不同的子序列 本题是在原来匹配子序列的基础上增加了统计所匹配的子序列个数&#xff0c;也就是dp数组的定义和更新公式和原来的有所区别。 1、dp数组的定义 dp[i][j]表示以i-1和j-1为末尾的字符串中&#xff0c;给定字符串s包含目标字符串t的个数。注意这里不是长度。…

vs2019成功连接数据库mysql

②在vs2019中创建新项目&#xff0c;注意x64 ③ 右击项目打开属性 ④添加include路径 ⑤添加lib路径 点击确定后点击应用 ⑥ 点击全部确定 ⑦ ⑧启动mysql 进入数据库&#xff1a; 在数据库中创建student的表 ⑨在va2019中输入下面代码测试 注意&#xff1a;密码换成自己…

大数据Flink(一百一十六):Flink SQL的时间属性

文章目录 Flink SQL的时间属性 一、Flink 三种时间属性简介 二、Flink 三种时间属性的应用场景 三、​​​​​​​SQL 指定时间属性的两种方式 四、​​​​​​​​​​​​​​SQL 处理时间DDL定义 五、​​​​​​​​​​​​​​SQL 事件时间DDL定义 Flink SQL的时…

Nature子刊|C4平台助力单细胞多组学分析,揭秘睾丸生殖细胞瘤的分子特征

在精准医疗的大潮中&#xff0c;单细胞多组学技术正成为研究肿瘤微环境的强有力工具。最近&#xff0c;一项发表在《Nature Communications》的重磅研究&#xff0c;就利用了包括DNBelab C Series在内的平台设备&#xff0c;对睾丸生殖细胞瘤&#xff08;Seminoma&#xff09;进…

矩阵分析 学习笔记3 多项式矩阵 jordan标准型

就是说这个矩阵里面的各个元素都是多项式&#xff0c;多项式的主角是类目大&#xff08;自变量&#xff09;。 多项式矩阵的秩是啥呢&#xff1f; 0多项式就是完全0的那种&#xff0c;就一个0&#xff0c;类目大都没有了。 多项式矩阵的秩和带一个类目大进去变成普通矩阵的秩不…

最大间距问题

LeetCode164 最大间距 基数排序 #include <iostream> #include <vector> using namespace std;class Solution { public:int maximumGap(vector<int>& nums) {int nnums.size();if(n<2) return 0;int exp1;int Maxnums[0];vector<int> buf(n)…

WD mybook10T硬盘exfat变0字节恢复方法

WD的mybook系列应该全部是3.5寸台式机机械硬盘然后加了盒子做成了移动存储&#xff0c;单盘容量已经极高了&#xff0c;此类盘出厂的文件系统一般为exfat&#xff08;可能是厂商为了方便mac客户使用&#xff09;。下边这个案例就是我们经常遇到的exfat变0字节。 故障存储:WD m…

用网卡的ap模式抓嵌入式设备的网络包

嵌入式设备不像pc上&#xff0c;有一些专门的工具比如wareshark来抓包&#xff0c;嵌入式设备中&#xff0c;有的可能集成了tcpdump&#xff0c;可以用来进行简单的抓包&#xff0c;但是不方便分析&#xff0c;况且有的嵌入式设备不一定就集成了tcpdump工具。 关于tcpdump工具…

[001-03-007].第07节:Redis中的事务

我的后端学习大纲 我的Redis学习大纲 1、Redis事务是什么&#xff1a; 1.可以一次执行多个命令&#xff0c;本质是一组命令的集合。一个事务中的所有命令都会序列化&#xff0c; 按顺序地串行化执行而不会被其他命令插入&#xff0c;不许加塞2.一个队列中&#xff0c;一次性、…

AI+RPA机器人 实现自动调用 kimi 的 AI 对话功能(内附使用教程)

前言 今天尝试写一个用RPA自动调用kimi的AI对话功能。 把这个写好之后&#xff0c;就是后面其他一切AI相关的基础&#xff0c;比如自动用AI写文章啊&#xff0c;比如搭建一个微信AI机器人啊等等&#xff0c; 都能用到今天实现的AI对话功能。 话不多说&#xff0c;直接看思路…