C++ 日期类的实现

目录

前言

日期类中的成员函数和成员变量

日期类中成员函数的详解和实现

1.天数前后的判断

2.天数加减的实现

[3.前置++ && 后置++](#3.前置++ && 后置++)

4.计算天数差值


前言

日期类的实现将综合前面所学的(类的6个默认成员函数),进一步理解和掌握类的6个默认成员函数。

若对(类的6个成员函数不太理解)请先看前文:

C++ 类与对象(中)-CSDN博客

C++ 类与对象(中)续-CSDN博客


日期类中的成员函数和成员变量

以下声明都在.h文件中

cpp 复制代码
class Date
{
public:
	//全缺省的构造函数
	Date(int year = 1, int month = 1, int day = 1);
	//运算符重载
	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+=(int day);
	Date operator+(int day);

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

	//前置++ 后置++
	Date& operator++();
	// 特殊处理:解决语法逻辑不自洽,自相矛盾的问题
	// d1++
	// 为了跟前置++区分,强行增加一个int形参,够成重载区分
	Date operator++(int);

	Date operator--(int);
	Date& operator--();

	// 天数-天数
	int operator-(const Date& d);

	// 本质就是inline(不声明和定义分离)
	//判断闰年还是平年
	int GetMonthDay(int year, int month)
	{
		assert(month > 0 && month < 13);
		static int monthDays[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

		// 365   自转  公转  365 5+h
		// 366
		if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
		{
			return 29;
		}

		return monthDays[month];
	}

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

private:
	int _year;
	int _month;
	int _day;
};

日期类中成员函数的详解和实现

1.天数前后的判断

这是 实现Date 类,对比较运算符 < 的重载定义。它比较两个 Date 对象,如果第一个日期早于第二个日期,则返回 true ,否则返回 false 。

以下是它的工作原理:

  1. 它比较两个日期的年份。如果第一个日期的年份小于第二个日期的年份,则返回 true 。

  2. 如果年份相等,则比较两个日期的月份。如果第一个日期的月份小于第二个日期的月份,则返回 true 。

  3. 如果月份相等,则比较两个日期的天数。如果第一个日期的天数小于第二个日期的天数,则返回 true 。

  4. 如果所有比较都为 false,则表示两个日期相等,因此返回 false 。

cpp 复制代码
bool Date::operator<(const Date& d)
{
	if (_year < d._year)
	{
		return true;
	}
	else if (_year == d._year)
	{
		if (_month < d._month)
		{
			return true;
		}
		else if (_month == d._month)
		{
			if (_day < d._day)
			{
				return true;
			}
		}
	}

	return false;
}

==运算符的实现,== 运算符通过比较 _year 、 _month 和 _day 来实现。如果三个成员变量都相等,则返回 true ,否则返回 false 。

cpp 复制代码
bool Date::operator==(const Date& d)
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}

<=运算符的实现,在上面我们实现了<和=连个运算符,在实现<=的时候我们就可以调用<和=运算符了。

cpp 复制代码
bool Date::operator<=(const Date& d)
{
	return *this < d || *this == d;
}

>运算符的实现,在上面我们实现了<=运算符,那么对<=运算符取反就可以了。

cpp 复制代码
bool Date::operator>(const Date& d)
{
	return !(*this <= d);
}

>=运算符的实现,要得到>=那么我们只需要对<运算符取反。

cpp 复制代码
bool Date::operator>=(const Date& d)
{
	return !(*this < d);
}

天数前后判断函数的测试:

cpp 复制代码
int main()
{
	Date d1(2024, 2, 3);
	Date d2(2024, 2, 1);
	cout << (d1 > d2) << endl;
	cout << (d1 < d2) << endl;
	cout << (d1 >= d2) << endl;
	cout << (d1 <= d2) << endl;
}

2.天数加减的实现

+=操作的实现,这个函数是 Date 类的成员函数,它将一个给定的天数添加到日期中。

它首先将给定的天数添加到 _day 中。然后,它检查 _day 是否大于该月的总天数。如果大于,则将 _day 减去该月的总天数,并将 _month 增加 1。如果 _month 等于 13,则将 _year 增加 1,并将 _month 重置为 1。

最后,它返回对当前对象的引用。

(注意:这里为什么是实现+=的操作,因为此时_day已经被改变,而+操作是不改变_day本身的)

cpp 复制代码
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;
}

+操作的实现,为了不修改当前对象_day,我们需要创建一个临时变量tmp,最后返回tmp的拷贝,实现+的操作。

cpp 复制代码
Date Date::operator+(int day)
{
	
	Date tmp = *this;
	tmp += day;

	return tmp;
}

接下来是-=和-操作的实现。

cpp 复制代码
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;
	tmp -= day;

	return tmp;
}

天数加减操作的测试:

cpp 复制代码
int main()
{
	Date d1(2024, 2, 3);
	Date d2 = d1 + 20;
	d2.Print();
	d1.Print();

	d2 -= 20;
	d2.Print();

	d1 += 30000;
	d1.Print();
}

日期计算器的结果:


3.前置++ && 后置++

前置++:返回+1之后的结果

注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率

cpp 复制代码
Date& Date::operator++()
{
	*this += 1;
	return *this;
}

后置++:

前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载

C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器 自动传递

注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存一份,然后给this + 1,而temp是临时对象,因此只能以值的方式返回,不能返回引用

cpp 复制代码
Date Date::operator++(int)
{
	Date tmp = *this;
	*this += 1;
	return tmp;
}

前置++ && 后置++的测试:

cpp 复制代码
int main()
{
	Date d1(2024, 2, 3);
	++d1;
	d1.operator++();
	d1.Print();

	d1++;//此写法自动识别
	d1.operator++(0);//这种写法传参帮助编译器识别
	d1.Print();

}

4.计算天数差值

计算两个日期之间的天数差。

首先检查两个日期的大小,并将较大的日期存储在 max 中,将较小的日期存储在 min 中。

然后,它使用一个循环来计算 min 到 max 之间的天数差。

最后,它返回天数差乘以一个标志位,该标志位表示两个日期之间的天数差是正数还是负数。

cpp 复制代码
int Date::operator-(const Date& d)
{
	int flag = 1;
	Date max = *this;
	Date min = d;

	if (*this < d)
	{
		int flag = -1;
		max = d;
		min = *this;
	}

	int n = 0;
	while (min != max)
	{
		++min;
		++n;
	}

	return n * flag;
}

计算天数差值函数的测试:

cpp 复制代码
int main()
{
    Date d1(2024, 2, 3);
    Date d2(2024, 2, 10);
    cout << (d2 - d1) << endl;

}

距离新年还剩7天了,提前祝大家新年快乐!!!

相关推荐
南东山人1 小时前
一文说清:C和C++混合编程
c语言·c++
Ysjt | 深4 小时前
C++多线程编程入门教程(优质版)
java·开发语言·jvm·c++
ephemerals__4 小时前
【c++丨STL】list模拟实现(附源码)
开发语言·c++·list
Microsoft Word4 小时前
c++基础语法
开发语言·c++·算法
一只小小汤圆4 小时前
opencascade源码学习之BRepOffsetAPI包 -BRepOffsetAPI_DraftAngle
c++·学习·opencascade
legend_jz5 小时前
【Linux】线程控制
linux·服务器·开发语言·c++·笔记·学习·学习方法
嘿BRE5 小时前
【C++】几个基本容器的模拟实现(string,vector,list,stack,queue,priority_queue)
c++
ö Constancy6 小时前
c++ 笔记
开发语言·c++
fengbizhe6 小时前
笔试-笔记2
c++·笔记