C++实现日期类Date(超详细)

news2024/11/17 21:24:16

个人主页:平行线也会相交💪
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创
收录于专栏【C++之路】💌
本专栏旨在记录C++的学习路线,望对大家有所帮助🙇‍
希望我们一起努力、成长,共同进步。🍓
在这里插入图片描述

目录

  • 日期类(Date.cpp)成员函数的实现
    • 构造函数
    • bool类型的运算符重载
    • 得到该月有几天GetMonthDay
    • 运算符重载+=和+
    • 运算符重载-=和-
    • 运算符重载前置++和后置++
    • 运算符重载前置--后置--
    • 两个日期相差几天
  • 日期类(Date.h)
  • 日期测试
    • TestDate1()
    • TestDate2()
    • TestDate3()
    • TestDate4()
    • TestDate5()
    • TestDate6()

日期类(Date.cpp)成员函数的实现

//构造函数,声明和定义分析不能同时给缺省参数,一般是声明给缺省参数
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;
	}
	else
	{
		cout << "非法日期" << endl;
	}
}

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

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

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

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

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

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

int Date::GetMonthDay(int year, int month)
{
	//由于要频繁调用daysArr,所以我们把daysArr放到静态区
	static int daysArr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	//if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0) && month == 2)
	if (month == 2 && ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)))
	{
		return 29;
	}
	else
	{
		return daysArr[month];
	}
	return daysArr[month];
}

//+=复用+
//Date& Date::operator+=(int day)
//{
//	*this = *this + day;
//	return *this;
//}

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)
		{
			_year++;
			_month = 1;
		}
	}
	return *this;
}

//+复用+=
Date Date::operator+(int day)
{
	Date tmp(*this);
	tmp += day;
	/*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;*/
	//出了作用域后tmp销毁,所以不能用引用返回
	return tmp;
}

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

Date Date:: operator-(int day)
{
	Date tmp = *this;//这里是拷贝构造
	tmp -= day;
	return tmp;
}

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

//后置++
//增加int参数并不是为了接收具体的值,这里仅仅是占位,为了就是跟前置++构成重载
Date Date::operator++(int)
{
	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;
}

//两个日期相差几天
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 n * flag;
}

构造函数

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;
	}
	else
	{
		cout << "非法日期" << endl;
	}
}

bool类型的运算符重载

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

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

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

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

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

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

得到该月有几天GetMonthDay

int Date::GetMonthDay(int year, int month)
{
	//由于要频繁调用daysArr,所以我们把daysArr放到静态区
	static int daysArr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	//if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0) && month == 2)
	if (month == 2 && ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)))
	{
		return 29;
	}
	else
	{
		return daysArr[month];
	}
	return daysArr[month];
}

运算符重载+=和+

这里有两种方式来写+=和+的赋值运算符重载。

先来看第一种:+=复用+的方式,请看:

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;
	/*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;*/
	//出了作用域后tmp销毁,所以不能用引用返回
	return tmp;
}

现在来看第二种写法,+=复用+

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;
		}
	}
	//出了作用域后tmp销毁,所以不能用引用返回
	return tmp;
}

//+=复用+
Date& Date::operator+=(int day)
{
	*this = *this + day;
	return *this;
}

现在这两种写法哪一种好呢?对于每种方式的+的赋值运算符重载没啥太大的区别(都要都要创建两个对象,一个是Date tmp(*this);,另外一个就是return tmp);但是对于+=的赋值运算符重载,第一种方式并没有创建对象,而第二种方式的+=的符重运算符重载由于又调用了一次+的赋值运算符重载函数(即多创建了两个对象)。所以最终第一种方式(+复用+=)显然更好一些,第二种方式差就差再+=复用+的时候多创建了两个对象

运算符重载-=和-

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

Date Date:: operator-(int day)
{
	Date tmp = *this;//这里是拷贝构造
	tmp -= day;
	return tmp;
}

运算符重载前置++和后置++

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

//后置++
//增加int参数并不是为了接收具体的值,这里仅仅是占位,为了就是跟前置++构成重载,方便区分
Date Date::operator++(int)
{
	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;
}

两个日期相差几天

//两个日期相差几天
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 n * flag;
}

日期类(Date.h)

class Date
{
public:
	//构造函数
	Date(int year = 22, int month = 5, int day = 20);

	//不需要写拷贝构造函数,所以下面可以选择直接注释掉
	Date (const Date& d)
	{
		cout << "Date(const Date& d)" << endl;
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

	bool operator<(const Date& x);
	bool operator==(const Date& x);
	bool operator<=(const Date& x);
	bool operator>(const Date& x);
	bool operator>=(const Date& x);
	bool operator!=(const Date& x);

	int GetMonthDay(int year, int month);

	Date& operator+=(int day);
	Date operator+(int day);
	Date& operator -=(int day);
	Date  operator-(int day);

	Date& operator++();//前置++
	Date operator++(int);//后置++
	Date& operator--();//前置--
	Date operator--(int);//后置++

	//计算两个日期相差多少天
	int operator-(const Date& d);
private:
	int _year;
	int _month;
	int _day;
};

日期测试

TestDate1()

在这里插入图片描述

void TestDate1()
{
	Date da1(23, 5, 20);
	da1 += 100;
	da1.Print();

	Date da2(23, 5, 20);
	Date da3(da2 + 100);
	da2.Print();
	da3.Print();

	//用一个已经存在的对象初始化另一个对象,即拷贝构造函数
	//拷贝构造的意义就是赋值初始化
	Date da4 = da2;//等价于Date da4(da2);//均为拷贝构造函数,是等价的

	//而赋值重载的意义纯粹的就是拷贝
	//已经存在的两个对象之间进行复制拷贝,即运算符重载函数
	da4 = da1;
}

这里指的注意的是Date da4 = da2;是等价于Date da4(da2);,因为这里实在用一个已经存在的对象初始化另外一个对象,所以这里调用的是拷贝构造函数,而不是调用=的赋值运算符重载
如下如:
在这里插入图片描述
在这里插入图片描述

TestDate2()

{
	Date da1(2021, 5, 21);
	//无论前置还是后置++都需要++
	//前置++就返回++以后的对象,后置++就返回++之前的对象

	//编译器这里成全一个同时委屈一个,为了区分这里的重载
	++da1;//da1.operator++()
	da1++;//da1.operator++(0)
	Date da2(2024, 5, 20);
	Date da3(2023, 3, 14);

	bool ret1 = da2 < da3;//自定义类型转换为对应的函数
	int i = 0, j = 2;
	bool ret2 = i < j;//内置类型编译器知道怎么比较,故编译器会自动处理内置类型的重载
}

TestDate3()

//测试日期类的-=
void TestDate3()
{
	Date da1(2023, 5, 20);
	da1 -= 50;
	da1.Print();

	Date da2(2023, 5, 21);
	da2 -= 88;
	da2.Print();

	Date da3(2023, 5, 25);
	da3 -= 100;
	da3.Print();

	Date da4(2024, 5, 20);
	da4 -= 10000;
	da4.Print();
}

TestDate4()

void TestDate4()
{
	Date d1(2020, 5, 20);
	d1 += 100;
	d1.Print();

	Date da2(2023, 5, 21);
	da2 += -100;
	da2.Print();

	Date da3(2023, 5, 5);
	da3 -= -100;
	da3.Print();
}

TestDate5()

void TestDate5()
{
	Date da1(2023, 5, 5);
	Date ret1 = da1--;//调用da1.operator(&da1,0);
	ret1.Print();
	da1.Print();

	Date da2(2023, 5, 5);
	Date ret2 = --da2;//调用da1.operator++(&da1);
	ret2.Print();
	da2.Print();
}

TestDate6()

void TestDate6()
{
	Date da1(2023, 5, 20);
	Date da2(2022, 5, 21);
	Date da3(1949, 10, 1);
	Date da4(2023, 5, 20);
	cout << da1 - da2 << endl;
	cout << da2 - da1 << endl;
	cout << da3 - da4 << endl;
	cout << da4 - da3 << endl;
}

好了,以上就是用C++来实现日期类。
就到这里,再见啦各位!!!

在这里插入图片描述

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

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

相关文章

C++笔试笔记2

C笔试笔记2 百富计算机的笔试 const限定符&#xff1a;首先作用于左边&#xff0c;如果左边没东西&#xff0c;就作用于右边。 const int&#xff1a; 左边没有内容&#xff0c;所以const作用于右边&#xff0c;就是“整型常量”。等同于int const&#xff1b; int * const&am…

NSS LitCTF部分wp

web 1、PHP是世界上最好的语言&#xff01;&#xff01; 直接cat flag flagNSSCTF{11eaebe0-3764-410d-be83-b23532a24235} 2、这是什么&#xff1f;SQL &#xff01;注一下 &#xff01; 直接查询&#xff0c;发现注入点是id 使用sqlmap列出所以数据库 ​sqlmap -u "h…

亚马逊,shopee,lazada卖家如何组建自己的测评团队

测评补单&#xff0c;这个话题在如今不管国内还是国外的电商行业已经是众所周知&#xff0c;它能够快速帮助自己的产品添加评论&#xff0c;获取排名&#xff0c;打造爆款&#xff0c;可以让用户更加真实、清晰、快捷的了解产品&#xff0c;以及产品的使用&#xff0c;快速上手…

低代码,或将颠覆开发行业?

前言 传统的软件开发过程往往需要耗费大量的时间和精力&#xff0c;因为开发人员需编写复杂的代码以完成各种功能。 低代码行业的发展&#xff0c;正好解决了这个问题&#xff0c;让复杂的代码编写一去不复返了。 文章目录 前言引入强大的平台总结 引入 低代码平台 是一种通过可…

【团购-HeaderView Objective-C语言】

一、那么,我们看上面这个东西,这就是我们保存在HeaderView里面的一个东西吧, HeaderView里面的一个东西, 1.因为这个东西,看起来,是不是也是一个这个样子,也是一个固定的样子啊, 所以我们这个UITableView的HeaderView,也可以使用一个xib来描述,也可以使用xib来描述,…

D. The Wu(数据范围)

Problem - D - Codeforces Childan正在编造一个传奇故事并试图出售他的伪造品——一条带有强烈“Wu”感的项链给Kasoura家族。但是&#xff0c;Kasoura先生正在质疑Childan故事的真实性。因此&#xff0c;他将询问有关Childan所谓的“个人珍藏”项链的一些问题。 这个“个人珍…

k8s系列(三)——补充内容

k8s架构补充 高可用集群副本数最好是 > 3 奇数个 master节点 scheduler 调度器&#xff0c;负责介绍任务&#xff0c;选择合适的节点进行分配任务 决定将任务分配至哪个node节点中&#xff0c;与api server进行交互 api server 所有服务访问的统一入口 压力巨大&…

计算机组成原理-计算机系统概述

目录 一&#xff0c;基本组成 二、各部件工作原理 2.1存储器 2.2运算器 2.3控制器 2.4输入设备 2.5输出设备 一条指令的工作原理 三、计算机系统的层次结构 三种基本语言 四、计算机性能指标 一&#xff0c;基本组成 “存储程序”的概念&#xff0c;指将指令以二进制代码的…

English Learning - L3 作业打卡 Lesson2 Day14 2023.5.18 周四

English Learning - L3 作业打卡 Lesson2 Day14 2023.5.18 周四 引言&#x1f349;句1: A brown out is an expression for a reduction in electric power.成分划分弱读连读爆破语调 &#x1f349;句2: Brown outs happen when there is too much demand for electricity.成分…

字节薪酬体系曝光,实在是太强了,真的不服不行...

曾经的互联网是PC的时代&#xff0c;随着智能手机的普及&#xff0c;移动互联网开始飞速崛起。而字节跳动抓住了这波机遇&#xff0c;2015年&#xff0c;字节跳动全面加码短视频&#xff0c;从那以后&#xff0c;抖音成为了字节跳动用户、收入和估值的最大增长引擎。 自从字节…

波奇学Linux:时间指令,查找指令,压缩指令,热键

日志&#xff1a;时间&#xff0c;日志等级&#xff0c;日志具体信息&#xff0c;其他信息用来记录程序信息 时间指令 data指令显示时间 修改时间显示格式 时间戳&#xff1a; date %s 时间戳&#xff1a;统一的时间格式&#xff0c;因为有时差原因&#xff0c;时间相对于各…

Python系列之文件操作和函数

感谢点赞和关注 &#xff0c;每天进步一点点&#xff01;加油&#xff01; 目录 一、文件操作 1.1 Shell里的文件操作 1.2 Python文件操作的步骤 1.3 Python打开和关闭文件 1.3.1 open 函数 1.4 文件定位 1.5 Python文件访问模式 1.5.1 只读模式 1.5.2 只写模式 1.5.…

大厂笔试真题解析

文章目录 2023/5/6 华为第一题&#xff1a;喷墨水2023/5/16 华为第二题&#xff1a;表达式计算 2023/5/6 华为第一题&#xff1a;喷墨水 模拟题&#xff0c;代码未提交&#xff0c;样例过 输入处理&#xff1a;双字节十六进制转二进制 十六进制转十进制再转二进制&#xff0c;…

Baklib盘点:企业做知识管理时遇到的困惑类型有哪些?

作为一家专注于企业知识管理的公司&#xff0c;Baklib深入了解了企业在进行知识管理时可能遇到的各种困惑。在此&#xff0c;我们盘点了企业做知识管理时遇到的困惑类型&#xff0c;并就如何解决这些困惑提出了建议。 企业做知识管理时遇到的困惑类型 知识流失 许多企业面临…

跨时钟域数据同步

跨时钟信号直接传输在信号跳变时违背本地时钟域的时序要求&#xff08;建立时间约束&#xff0c;保持时间约束&#xff09;&#xff0c;容易产生亚稳态&#xff0c;无法确定亚稳态何时结束以及结束时保持在何种状态上。 用同步器抑制亚稳态的往下传播的概率&#xff0c;根据情…

一文详解Pytorch中的Tensor操作

何为Tensor&#xff1f; Tensor的英文原义是张量&#xff0c;PyTorch官网对其的定义如下&#xff1a; 也就是说&#xff0c;一个Tensor是一个包含单一数据类型的多维矩阵。通常&#xff0c;其多维特性用三维及以上的矩阵来描述&#xff0c;例如下图所示&#xff1a;单个元素为…

CloudCompare二次开发之如何通过PCL进行点云曲面重建?

文章目录 0.引言1.CloudCompare界面设计重建(reconstruct)按钮2.使用贪婪三角化进行曲面重建&#xff08;Surface_Rec&#xff09; 0.引言 因笔者课题涉及点云处理&#xff0c;需要通过PCL进行点云数据一系列处理分析&#xff0c;查阅现有网络资料&#xff0c;对常用PCL点云曲面…

SD webui 手记

源代码地址&#xff1a; https://github.com/AUTOMATIC1111/stable-diffusion-webui git拉取代码后&#xff0c;windows下支持根目录直接运行 webui-user.bat&#xff0c;前提本地需要先安装python环境&#xff0c;略过&#xff0c;我们直接跑源码玩 安装依赖 pip install …

Linux 指令(二)+完整思维导图+实图例子+深入细节+通俗易懂建议收藏

绪论 对于指令的学习&#xff0c;是一个漫长的过程&#xff0c;因为一般在后台服务器上为了减少刷新图形化界面消耗资源都是呈现出命令行的形式&#xff0c;对此我们必选要掌握好Linux的指令。今天我们接着上一章的指令来继续学习更多的指令。 话不多说安全带系好&#xff0c;发…

字节给我狠狠上了一课:危机来的时候你连准备时间都没有!

各大互联网公司的接连裁员&#xff0c;政策限制的行业接连消失&#xff0c;让今年的求职雪上加霜&#xff0c;想躺平却没有资本&#xff0c;还有人说软件测试岗位饱和了&#xff0c;对此很多求职者深信不疑&#xff0c;因为投出去的简历回复的越来越少了。甚至还有不少大厂直接…