用运算符重载通过对日期类的操作,从而实现日历中的推演日期、加减日期得到天数等功能。
加减等操作
Date& operator += (int day)
+=后将会得到一个新日期,为减少拷贝,可以使用传引用返回。
要得到每月对应的天数,就需要实现一个函数。
int GetMonthDay(int year, int month)
{
int a[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
//先判断是否是二月再判断是否是闰年,否则会浪费时间每次进行判断
if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))
{
return 29;
}
return a[month];
}
接下来实现函数主体:
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 operator + (int day)
这里就可以不用再进行计算,可以直接复用 += 的代码。
Date operator+(int day)
{
Date tmp = *this;
tmp += day;
return tmp;
}
但这里就不可以是传引用返回,因为 tmp 是该函数局部定义的,出了作用域便会被销毁,如果传引用返回会出错,出现野引用的错误。野引用和野指针相似,就是错误的指向不存在已经销毁的空间,一定要注意。
+=操作是不一样,其改变的是其本身,出了函数作用域不会销毁,故可以用传引用返回。
Date& operator -= (int day)
-=和+=类似:
代码实现为:
Date& operator-=(int day)
{
_day -= day;
while (_day <= 0)
{
_month--;
if (_month == 0)
{
_month = 12;
_year--;
}
//借上一个月的天数
_day += GetMonthDay(_year, _month);
}
return *this;
}
Date operator - (int day)
同样,这里直接复用 -= 的代码即可。
Date operator-(int day)
{
Date tmp = *this;
tmp -= day;
return tmp;
}
Date& operator++()
这里还有++运算符,但由于前置++和后置++最后返回值不同以及为了区分,C++规定为了区分,构成重载,给后置++强⾏增加了⼀个int形参,这⾥不需要写形参名,因为接收值是多少并不重要,也不需要⽤,这个参数仅仅是为了跟前置++构成重载进行区分。
要实现++很容易,而且前置++是先++,后使用,可以使用传引用返回,只要复用+=即可。
Date& operator++()
{
*this += 1;
return *this;
}
Date operator++(int)
后置++要先使用,后++,所以要定义一个临时变量来存储并返回日期,然后再复用+=改变日期。
Date operator++(int)
{
Date tmp = *this;
*this += 1;
return tmp;
}
Date& operator--()
类似的,复用 -= 即可。
Date& operator--()
{
*this -= 1;
return *this;
}
Date operator--(int)
与后置++类似。
Date operator--(int)
{
Date tmp = *this;
*this -= 1;
return tmp;
}
比较大小操作
比较不同日期的时间的先后顺序。
bool operator < (const Date& d)
比较日期,要依次比较,先比较年,再比较月,再比较日:
bool 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)
{
//月相等,比较日
return _day < d._day;
}
}
//如果不符合上述条件的,说明前者大于后者
return false;
}
bool operator==(const Date& d)
年月日都相等,则日期相等。
bool operator==(const Date& d)
{
return _year == d._year && _month == d._month && _day == d._day;
}
bool operator <= (const Date& d)
也就前者日期小于或等于后者日期即可,直接复用<和==。
bool operator <= (const Date& d)
{
return *this < d || *this == d;
}
bool operator>(const Date& d)
即<=的非。
bool operator>(const Date& d)
{
return !(*this <= d);
}
bool operator >= (const Date& d)
<的非
bool operator >= (const Date& d)
{
return !(*this < d);
}
bool operator != (const Date& d)
==的非
bool operator != (const Date& d)
{
return !(*this == d);
}
int operator-(const Date& d)
日期减日期得到的是中间相差的天数。最简单的,直接通过计数得到相差的天数即可。中间会用到拷贝构造、赋值重载,< 、!= 、++ 等运算符重载。
int operator-(const Date& d)
{
Date max = *this;
Date min = d;
if (*this < d)
{
max = d;
min = *this;
}
int n = 0;
while (max != min)
{
min++;
n++;
}
return n;
}
完整代码
#include<iostream>
class Date
{
public:
// 全缺省的构造函数
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
if (!CheckDate())
{
std::cout << "非法日期" << std::endl;
}
}
// 拷贝构造函数
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
// 赋值运算符重载
Date& operator=(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
return *this;
}
// 析构函数
//日期类无要释放的资源,编译器自动生成的析构即可满足要求。
void Print()
{
std::cout << _year << "-" << _month << "-" << _day << std::endl;
}
//检查日期是否正确
bool CheckDate()
{
if (_month < 1 || _month>12 || _day<1 || _day>GetMonthDay(_year, _month))
{
return false;
}
else
{
return true;
}
}
// 某年某月的天数
int GetMonthDay(int year, int month)
{
int arr[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
if (month == 2 && ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)))
{
return 29;
}
return arr[month];
}
// 日期+=天数
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 operator+(int day)
{
Date tmp = *this;
tmp += day;
return tmp;
}
// 日期-天数
Date operator-(int day)
{
Date tmp = *this;
tmp -= day;
return tmp;
}
// 日期-=天数
Date& operator-=(int day)
{
_day -= day;
while (_day <= 0)
{
_month--;
if (_month == 0)
{
_month = 12;
_year--;
}
//借上一个月的天数
_day += GetMonthDay(_year, _month);
}
return *this;
}
// <运算符重载
bool 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)
{
//月相等,比较日
return _day < d._day;
}
}
//如果不符合上述条件的,说明前者大于后者
return false;
}
// <=运算符重载
bool operator <= (const Date& d)
{
return *this < d || *this == d;
}
// >运算符重载
bool operator>(const Date& d)
{
return !(*this <= d);
}
// >=运算符重载
bool operator >= (const Date& d)
{
return !(*this < d);
}
// ==运算符重载
bool operator==(const Date& d)
{
return _year == d._year && _month == d._month && _day == d._day;
}
// !=运算符重载
bool operator != (const Date& d)
{
return !(*this == d);
}
// 日期-日期 返回天数
int operator-(const Date& d)
{
Date max = *this;
Date min = d;
if (*this < d)
{
max = d;
min = *this;
}
int n = 0;
while (max != min)
{
min++;
n++;
}
return n;
}
// 前置++
Date& operator++()
{
*this += 1;
return *this;
}
// 后置++
Date operator++(int)
{
Date tmp = *this;
*this += 1;
return tmp;
}
// 后置--
Date operator--(int)
{
Date tmp = *this;
*this -= 1;
return tmp;
}
// 前置--
Date& operator--()
{
*this -= 1;
return *this;
}
private:
int _year;
int _month;
int _day;
};
void test()
{
Date d1(2024, 6, 6);
Date d2(2006, 1, 2);
int n = d1 - d2;
std::cout << n << std::endl;
d2 += n;
if (d1 == d2)
{
std::cout << "true" << std::endl;
}
d1++;
++d2;
}
int main()
{
test();
return 0;
}