前引: 在软件开发中,时间与日期的处理是基础但极具挑战性的任务。传统的手工日期运算逻辑往往面临闰年规则、月份天数动态变化、时区转换等复杂场景的容错难题,且代码冗余度高、可维护性差。本文将深入探讨如何利用C++的面向对象特性与成员函数封装能力,构建一个高内聚、低耦合的日期推算系统。

 本文目的:深度 巩固+运用 C++运算符重载成员函数,细节夯实!

目录

实践引入

运算符重载实践—日期比大小

类的创建

日期比较

日期相等判断

 日期小于判断

日期小于等于判断

日期大于判断

日期大于等于判断

总结

运算符重载实践—日期推算

类的创建

日期推算(后)

计算当月天数

日期进位计算

测试

变式

 日期推算(前)

日期退位计算

测试 

日期推算(前置++)

测试

日期推算(前置--)

测试

 日期推算(后置--)

测试

 运算符重载实践—日期间隔


实践引入

我们日常生活中对于日期的使用很广泛,例如:距离高考***天、今天是*年*月*日.......

大家可以点击下面这个链接体验一下对于时间的计算:

https://onlinealarmkur.com/date/zh-cn/https://onlinealarmkur.com/date/zh-cn/

最近咱们学习的类和对象中 运算符重载成员函数 就可以来简单实现这个功能!

运算符重载实践—日期比大小

类的创建

既然是日期计算,那么还和上面的类一样,需要有年、月、日

class Timedate
{
public:
	//构造函数
	Timedate(int year = 2025, int month = 5, int day = 9)
	{
		_year = year;
		_month = month;
		_day = day;
	}

private:
	int _year;
	int _month;
	int _day;
};
日期比较
日期相等判断

咱们得成员函数可以只在类里面进行声明,在另一个文件来完成函数的实现,需要注明函数来历!

//成员函数定义
bool Timedate::operator==(const Timedate St2)
{
	if (_year == St2._year && _month ==St2._month && _day == St2. _day)
	{
		return true;
	}
	return false;
}

注意咱们的函数调用,以下两种调用方式是相等的(为了体验运算符重载的简洁性,选第二种)

St1 == St2;
 
St1.operator==(St2);
 日期小于判断

按照上面的流程,我们先在成员函数里面声明

bool operator<(const Timedate St2);

然后跨文件实现该函数的定义

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

日期小于等于判断

还是先写成员函数声明

bool operator<=(const Timedate St2);

随后重点来了!

第一种:我们可以和上面一样,通过 if 语句去判断来返回不同的值

第二种:咱们小于等于的判断不就是前面两个结合起来吗?所以我们可以调用上面两个函数,如下

bool Timedate::operator<=(const Timedate St2)
{
	return ((*this) < St2 || (*this) == St2);
}

 这里隐藏的 this 指针是指向 St1 的,这里其实跟函数调用一样,只是需要理解隐藏的 this 指针

St1 < St2;
(*this) < St2;
//二者等价
日期大于判断

有了前面的基础,我们同样有两种写法:

第一种:走 if 判断

第二种:“大于”条件不是刚好和“小于等于”相反吗!所以我们还是采用调用函数的方法来实现

bool operator>(const Timedate St2);
bool Timedate::operator>(const Timedate St2)
{
	return !((*this) < St2 || (*this) == St2);
}
日期大于等于判断

第一种:直接走 if 判断

第二种:调用运算符重载函数(大于等于与小于刚好互补)如下:

bool operator>=(const Timedate St2);
bool Timedate::operator>=(const Timedate St2)
{
	return !((*this) < St2);
}
总结

(1)运算符重载成员函数大大减少了代码量

(2)其次增加了代码表达的效果,对比之前的函数:需要有函数名、参数,而现在我们根据运算符就可以明了的判断出这个函数的功能,这是很直观的,较C语言一个大的进阶!

St1 == St2
St1 < St2
St1 <= St2
St1 > St2
St1 >= St2

运算符重载实践—日期推算

类的创建

 既然是日期计算,那么还和上面的类一样,需要有年、月、日

class Timedate
{
public:
	//构造函数
	Timedate(int year = 2025, int month = 5, int day = 9)
	{
		_year = year;
		_month = month;
		_day = day;
	}
 
private:
	int _year;
	int _month;
	int _day;
};
日期推算(后)

功能:给一个天数,自当前日期开始,推算一定天数之后的日期

计算当月天数

功能:计算给定的这个月有多少天

因为会面临加法计算,对月或者年需要进位,所以我们需要知道当月的准确天数是多少

设计功能:

(1)可以通过 case 语句判断当月天数,最后判断是不是闰年,因为闰年的2月有29天

(2)通过 if 语句判断,根据给定的月直接确定天数,再走闰年的判断

//计算当月天数
int Timedate::Compute(int _year, int _month)
{
	//我们这里就拿case语句判断
	switch (_month)
	{
	case 1:
	case 3:
	case 5:
	case 7:
	case 8:
	case 10:
	case 12:
		return 31;
	case 4:
	case 6:
	case 9:
	case 11:
		return 30;
	case 2:
		if (_year % 4 == 0 && _year % 100 != 0 || _year % 400 == 0)
		{
			return 29;
		}
		else
			return 28;
	}
}

下面我们来测试一下这个功能:

日期进位计算

我们只需要在一个循环对年、月进行进位计算,等循环结束再将剩余天数相加即可

不管咋样,我们直接加上天数,然后根据对应月的满天数去减即可

注意:我们是推算对应天数之后,所以不改变原来的日期,需要建立新对象

//推算进位
Timedate Timedate::operator+(int day)
{
	//既然是加,那么我们不能改变原来的日期,调用拷贝构造
	Timedate St3(*this);
	//对月进位
	St3._day += day;
	while (St3._day > Compute(St3._year,St3._month))
	{
		//日减少
		St3._day -= Compute(St3._year, St3._month);
		//月增加
		St3._month++;
		//如果超过12月,年进位,重置月份
		if (St3._month > 12)
		{
			St3._year++;
			St3._month = 1;
		}
	}
	return St3;
}
测试

变式

上面是不改变原来的日期,如果我们现在需要改变呢?

很简单,我们只需要调用刚才的函数,再利用编译器默认的运算符重载函数赋值即可

函数声明:

Timedate& operator+=(int day);

函数实现:

Timedate& Timedate::operator+=(int day)
{
	return *this = ((*this) + 100);
}

然后利用编译器默认的运算符重载函数进行浅拷贝内置类型

这里补充一下:

因为我们没有写“等于”的运算符重载函数,编译器就会调用自己默认的运算符重载函数完成

(1)对内置类型发生浅拷贝

(2)自定义类型调用自己的重载函数(会直接更改地址) 

 日期推算(前)

有了上面的经验,日期推算前就是往前推一定天数之前的日期是多少

类的结构还是与上面的一样,下面我们来完成函数

日期退位计算
Timedate operator-(int day);

执行函数:

先更新月、再根据月判断年,最后更新天数

 
Timedate Timedate::operator-(int day)
{
	//先拷贝构造一个一模一样的对象,防止更改原来的日期
	Timedate St3(*this);
	//直接减去天数
	St3._day -= day;
	while (St3._day < 1)
	{
		//小于1说明不符合规定
		//应该先减月
		St3._month--;
		//如果月小于1,说明要更新年了
		if (St3._month < 1)
		{
			St3._year--;
			St3._month = 12;
		}
		//再加天数
		St3._day += Compute(St3._year, St3._month);
	}
	return St3;
}
测试 

日期推算(前置++)

前置加加是返回加完之后的结果,这点需要和后置加加区别。类的类型不变,我们直接进入函数

函数声明:

Timedate& operator++();

 函数实现:

Timedate& Timedate::operator++()
{
	//此时this指针传过来的就是调用函数的对象
	_day++;
	while (_day > Compute(_year, _month))
	{
		//如果超过当月天数
		_day -= Compute(_year, _month);
		//月加1
		_month++;
		//判断12月以上的情况
		if (_month > 12)
		{
			_year++;
			_month = 1;
		}
	}
	return *this;
}

注意*this指向的对象是调用函数的对象,是全局生命域,所以可以使用引用

测试

日期推算(前置--)

函数声明:

Timedate& operator--();

函数实现:

Timedate& Timedate::operator--()
{
	_day --;
   //如果不满足月的要求,就退治
	while (_day < 1)
	{
		_month--;
		if (_month < 1)
		{
			_month = 12;
			_year--;
		}
		_day += Compute(_year, _month);
	}
	return *this;
}
测试

 日期推算(后置--)

后置唯一需要注意的是它的函数调用与前置减减达成重复,所以我们需要用一个参数进行区分

函数声明:

Timedate operator--(int);

函数实现:

Timedate Timedate::operator--(int)
{
	//拷贝构造
	Timedate St3(*this);
	_day--;
	while (_day < 1)
	{
		_month--;
		if (_month < 1)
		{
			_month = 12;
			_year--;
		}
		_day += Compute(_year, _month);
	}
	return St3;
}
测试

 运算符重载实践—日期间隔

有了上面的基础我们完成这个功能就很简单了!

第一种:最简单的多次调用“加加”函数,每调用一次,计数一次

第二种:分区段(第一次保证年相同,第二次再保证月、日相同)实现

第一种更加的直观,所以我们选择第一种!
函数声明:

int operator-(const Timedate St2);

函数实现:

(1)为了避免改变原对象,我们新建两个临时对象

(2)先假设其中一个对象较大,如果假设不成立,再将二者调换

(3)通过循环来多次调用“相等”运算重载函数,并且不断计数

(4)根据假设结果返回正负值,来直观的判断日期先后

int Timedate::operator-(const Timedate St2)
{
	//假设第一个参数更大
	Timedate St3 = (*this);
	Timedate St4 = St2;
	//用于返回正负值
	int flag = 1;
	//计数
	int date = 0;
	//调用运算重载函数确定大小
	if (St3 < St4)
	{
		St3 = St4;
		St4 = *this;
		flag = -1;
	}
	//计算差值
	while (!( St3 == St4))
	{
		++St4;
		++date;
	}
 
	return flag * date;
}

                                                【雾非雾】期待与你的下次相遇! 

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐