一、全部源码展示
#include<iostream>
using namespace std;
class Date
{
public:
// 构造函数
Date(int year = 1900, int month = 1, int day = 1)
:_year(year), _month(month), _day(day)
{}
// 打印日期
void Print() const
{
cout << _year << "年" << _month << "月" << _day << "日" << endl;
}
// 获取当月天数,静态工具函数
static int GetMonthDay(int year, int month)
{
static int monthDays[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
// 闰年判断
if (month == 2)
{
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
return 29;
}
return monthDays[month];
}
// 复合赋值 += 日期加天数(修改自身)
Date& operator+=(int day);
// 复合赋值 -= 日期减天数(修改自身)
Date& operator-=(int day);
// 日期 + 天数,返回新日期,不修改自身
Date operator+(int day) const;
// 日期 - 天数,返回新日期,不修改自身
Date operator-(int day) const;
// 两个日期相减,返回相差天数
int operator-(const Date& d) const;
private:
int _year;
int _month;
int _day;
// 私有工具:日期向前减一天
void SubOneDay();
// 私有工具:日期向后加一天
void AddOneDay();
};
// += 重载:当前日期增加day天
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;
}
// -= 重载:当前日期减少day天
Date& Date::operator-=(int day)
{
if (day < 0)
{
return *this += -day;
}
for (int i = 0; i < day; i++)
{
SubOneDay();
}
return *this;
}
// 日期 + 天数,生成新对象不改变原对象
Date Date::operator+(int day) const
{
Date tmp = *this;
tmp += day;
return tmp;
}
// 日期 - 天数,生成新对象不改变原对象
Date Date::operator-(int day) const
{
Date tmp = *this;
tmp -= day;
return tmp;
}
// 私有:往前推一天
void Date::SubOneDay()
{
_day--;
if (_day == 0)
{
_month--;
if (_month == 0)
{
_year--;
_month = 12;
}
_day = GetMonthDay(_year, _month);
}
}
// 私有:往后推一天
void Date::AddOneDay()
{
_day++;
if (_day > GetMonthDay(_year, _month))
{
_day = 1;
_month++;
if (_month == 13)
{
_year++;
_month = 1;
}
}
}
// 两个日期相减,返回相差总天数
int Date::operator-(const Date& d) const
{
Date maxDate = *this;
Date minDate = d;
int count = 0;
bool flag = false;
if (*this < d)
{
maxDate = d;
minDate = *this;
flag = true;
}
while (!(maxDate == minDate))
{
minDate.AddOneDay();
count++;
}
return flag ? -count : count;
}
// 补充==、<比较运算符(日期相减依赖)
bool operator==(const Date& d1, const Date& d2)
{
return d1._year == d2._year && d1._month == d2._month && d1._day == d2._day;
}
bool operator<(const Date& d1, const Date& d2)
{
if (d1._year < d2._year)
return true;
if (d1._year == d2._year && d1._month < d2._month)
return true;
if (d1._year == d2._year && d1._month == d2._month && d1._day < d2._day)
return true;
return false;
}
// 测试主函数
int main()
{
// 1. 日期加天数测试:2026.3.1 + 1000天
Date d1(2026, 3, 1);
Date resAdd = d1 + 1000;
cout << "2026年3月1日加1000天:";
resAdd.Print();
// 2. 日期减天数测试
Date d2(2028, 11, 25);
Date resSub = d2 - 1000;
cout << "2028年11月25日减1000天:";
resSub.Print();
// 3. 两个日期相减,求间隔天数
Date start(2026, 3, 1);
Date end(2028, 11, 25);
int gap = end - start;
cout << "两个日期相差天数:" << gap << "天" << endl;
return 0;
}
二、功能整体说明
operator+/operator-:日期 ± 天数,返回全新日期对象,不修改原日期;operator+=/operator-=:复合赋值,直接修改当前日期自身,支持链式调用;operator-(两个Date对象):重载减法,计算两个日期之间相差的总天数,支持正负;- 内置静态工具
GetMonthDay自动区分平闰年,正确获取 2 月天数; - 封装私有
AddOneDay/SubOneDay实现单天进退位,简化上层逻辑。
三、核心运算符重载原理拆解
1. 复合赋值 += /-=(修改自身,返回引用)
复合赋值运算符语义是改变调用对象本身 ,所以返回Date&引用,支持连续运算如d += 100 += 50。 逻辑:
+=:天数累加后循环判断是否超过当月最大天数,超则进月、进年;-=:循环逐天向前递减,遇到月初自动退至上一年 / 上月。
2. 普通运算符 + /-(不修改原对象,返回临时拷贝)
数学上 日期 + 天数 不会改变原本日期,因此实现逻辑:
- 拷贝一份当前日期临时对象 tmp;
- 对 tmp 使用
+=/-=完成计算; - 返回临时对象,原对象保持不变。
3. 两个日期相减 operator-(Date d)
重载两个 Date 对象相减,用于计算间隔天数:
- 比较两个日期大小,区分最大、最小日期;
- 最小日期逐天向后累加,直到与大日期相等,统计累加次数;
- 如果传入顺序是大日期减小日期,返回正数,反之返回负数。 该功能依赖
==相等重载、<小于比较重载辅助判断。
4. 闰年与月份天数处理
静态函数GetMonthDay使用 static 数组存储平年每月天数,仅初始化一次提升性能; 闰年规则严格遵循:四年一闰、百年不闰、四百年再闰,仅 2 月特殊返回 29 天。
四、测试用例运行结果
main 函数内置三组测试:
-
2026 年 3 月 1 日 + 1000 天,输出 2028 年 11 月 25 日;
-
2028 年 11 月 25 日 - 1000 天,还原 2026 年 3 月 1 日;
-
两个日期相减直接输出间隔 1000 天。 运行输出:
2026年3月1日加1000天:2028年11月25日 2028年11月25日减1000天:2026年3月1日 两个日期相差天数:1000天