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

news2025/1/12 1:40:18

个人主页:平行线也会相交💪
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创
收录于专栏【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/547839.html

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

相关文章

六级备考28天|CET-6|听力第二讲|长对话满分技巧|听写技巧|2022年6月考题|14:30~16:00

目录 1. 听力策略 2. 第一二讲笔记 3. 听力原文复现 (5)第五小题 (6)第六小题 (7)第七小题 (8)第八小题 扩展业务 expand business 4. 重点词汇 1. 听力策略 2. 第一二讲笔记 3. 听力原文复现 (5)第五小题 our guest is Molly Sundas, a university stud…

【ZYNQ】ZYNQ7000 定时器及私有定时器驱动示例

简介 每个 Cortex-A9 处理器都有自己独立的 32 位私有定时器和 32 位看门狗定时器。这两个处理器共享一个 64 位的全局定时器。这些计时器的频率为 CPU 频率&#xff08;CPU_3x2x&#xff09;的 1/2。 在系统级别上&#xff0c;有一个 24 位看门狗定时器和两个 16 位三重定时…

据不可靠消息,ST的新一代机皇正式命名为STM32V8系列,搭载Cortex-M85内核

根据以往的传统单片机命名方式&#xff1a; C0, L0, G0, F0 > Cortex-M0内核 F1, L1 > Corterx-M3内核 F2, F3 > Corterx-M3/M4 F4&#xff0c;G4&#xff0c;L4, L4 > Cortex-M4内核 L5&#xff0c;U5, H5 > Cor…

数据结构—排序算法(插入排序及选择排序)

目录 1、排序的概念 2、常见的排序算法 3、直接插入排序&#xff08;插入排序&#xff09; 3.1 直接插入排序基本思想 3.2 直接插入排序实现 4、 希尔排序( 缩小增量排序 )&#xff08;插入排序&#xff09; 4.1 基本思想 4.2 希尔排序实现 4.3 希尔排序的特性总结 5、…

【Draw.io】让Draw.io导出的SVG格式图片包含自定义属性信息

前景提要 Draw.io重度用户一枚 这个Draw.io是一个极其好用的跨平台流程图绘制软件。 它保存的文件格式可以输出成SVG格式. 这个是基本功能了&#xff0c;没啥好说的 导出之后得到画的图片的SVG代码 SVG代码&#xff0c;也没啥好说的&#xff0c;一种矢量图片格式。 但是&…

改造Springboot+vue项目

准备 搜索一个项目&#xff0c;并成功运行 毕设时&#xff0c;我们可以从网上搜索一个项目&#xff08;包括前端的页面、后台的处理、数据库等有一下简单的模板样式&#xff09;并能成功的将项目在自己的电脑上跑起来。毕设项目可以用搜索的模板&#xff08;不用从头开始写&a…

【数据结构】_2.包装类与泛型

目录 1. 包装类 1.1 基本数据类型和对应的包装类 1.2 &#xff08;自动&#xff09;装箱和&#xff08;自动&#xff09;拆箱 1.2.1 装箱与拆箱 1.2.2 自动装箱与自动拆箱 1.3 valueOf()方法 2. 泛型类 2.1 泛型类与Object类 2.2 泛型类语法 2.3 泛型类示例 2.4 裸类…

怎么把照片缩小到200k?图片指定大小压缩怎么弄?

平时在给账号设置头像时&#xff0c;都会遇到图片过大无法上传的情况&#xff0c;这时候我们可以通过图片压缩指定大小工具来将图片压缩到200kb以下&#xff0c;这样就可以顺利设置头像了&#xff0c;下面一起来看一下图片指定大小压缩&#xff08;https://www.yasuotu.com/ima…

机器学习笔记 - windows基于TensorRT的UNet推理部署

一、TensorRT简介 NVIDIA TensorRT是一个用于高性能深度学习推理的平台。TensorRT适用于使用CUDA平台的所有NVIDIA GPU。所以如果需要基于TensorRT部署,至少需要一个NVIDIA显卡,算力5.0以上,比Maxwell更新的架构,可以参考下表。 CUDA GPUs - Compute Capability | NVIDIA …

电动车头盔检测数据集

现在正慢慢整理自己有关电动车头盔检测的项目内容&#xff0c;会逐渐将这些资源进行发布&#xff0c;供大家参考和使用【部分资源有偿提供&#xff0c;毕竟花费了很多心血】。 这篇文章主要是发布相关数据集的。网上关于工厂环境下的头盔数据集有很多&#xff0c;而且多种多样…

PFCdocumentation_Coupling PFC and FLAC3D

目录 Coupling PFC and FLAC3D 1D Structural Element Coupling Scheme Wall-Zone Coupling Scheme 2D 3D Ball-Zone Coupling Scheme Commands FISH Functions Coupling PFC and FLAC3D 在 FLAC3D 图形用户界面中&#xff0c;可以通过“工具 ‣ 加载 PFC”菜单项加载 …

计算机组成与结构易错题

计算机组成与结构 海明校验码是在n个数据位之外增设k个校验位&#xff0c;从而形成一个kn位的新的码字&#xff0c;使新的码字的码距比较均匀地拉大。n与k的关系是&#xff08;A&#xff09;。 A、2k-1≥nk B、2n-1≤nk C、nk D、n-1≤k 知识&#xff1a; 确定要传输的信息&…

普通专科生,拿什么拯救自己的未来我想成为一名网络安全专业人员,需要做什么?

前 言 写这篇文章的初衷是很多朋友都想了解如何入门/转行网络安全&#xff0c;实现自己的“黑客梦”。文章的宗旨是&#xff1a; 1.指出一些自学的误区 2.提供客观可行的学习表 3.推荐我认为适合小白学习的资源.大佬绕道哈&#xff01; 我的经历&#xff1a; 我19年毕业&…

【C语言】入门必看之循环练习(含二分查找动图)

&#x1f6a9;纸上得来终觉浅&#xff0c; 绝知此事要躬行。 &#x1f31f;主页&#xff1a;June-Frost &#x1f680;专栏&#xff1a;C语言 ⚡注&#xff1a;此篇文章的 代码风格部分 将根据《高质量 C/C 编程指南》 —— 林锐 进行说明。该部分将用紫色表示 该篇将对循环语…

AI落地:10分钟变身Excel高手

本文首发公众号突围一只鹰。 使用Excel的时候经常有几个难点&#xff1a; 有些功能不知道如何操作不知道该用哪个公式不知道公式的参数如何设置复杂数据处理不知道如何写公式多表链接的时候不知道如何写公式其他数据源导入Excel只会手动录入 有了ChatGPT之后&#xff0c;很多…

求爷爷告奶奶,阿里大佬才甩出这份Spark+Hadoop+中台实战pdf

Spark大数据分析实战 1、Spark简介 初识Spark Sp ark生态系统BDAS Sp ark架构与运行逻辑 弹性分布式数据集 2、Spark开发与环境配置 Spark应用开发环境2置 使用Intelli i开发Spark 远程调试Spark程序 Spark编译 配置Spark源码阅读环境 3、BDAS简介 SQL on Spark S…

Windows使用flask部署HTML网页的方法

使用Flask python运行设计的好的html网页&#xff0c;已经配套的css和js文件&#xff1a; 前提条件 html、css 和 js 在同一个目录之下 html 内使用 css 和 js &#xff0c;需要使用相对路径flask python 程序可以和 html 不在同一个目录 即&#xff1a;python程序可以在D盘…

sql server 数据库

1、窗口函数 sqlserver中窗口函数和OVER()函数_lfw2019的博客-CSDN博客参考&#xff1a;https://blog.csdn.net/qq_41805514/article/details/81772182 https://blog.csdn.net/qq_27997957/article/details/82383328一、OVER() 函数  语法结构&#xff1a;OVER([ PARTITION B…

【C++初阶】动态内存管理

一.C内存分布 说明&#xff1a; 1. 栈又叫堆栈--非静态局部变量/函数参数/返回值等等&#xff0c;栈是向下增长的&#xff1b; 2. 内存映射段是高效的I/O映射方式&#xff0c;用于装载一个共享的动态内存库。用户可使用系统接口 创建共享共享内存&#xff0c;做进程间通信&…

【Leetcode刷题】算法:合并两个有序链表

文章目录 一、题目介绍二、解决办法三、提交结果 一、题目介绍 二、解决办法 首先定义一个名为ListNode的类&#xff1a; class ListNode:def __init__(self, val0, nextNone):self.val valself.next nextListNode代表一个链表节点&#xff0c;每个节点包含一个值&#xff…