学完运算符重载和友元函数,我们就应该学会运用这些函数,而写一个日期类的代码基本包含了运算符重载的大部分东西。
接下来就看一看这个日期类的到底该怎么写。
首先,简单接介绍一下这个日期类的基本功能:
// 当前日期days天后是什么日期?
Date operator+(int days);
// 当前日期days天前是什么日期?
Date operator-(int days);
// 两个日期之间差了多少天?
int 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=(const Date& d);
// 重载取地址符号
Date* operator&();
// 前置++
Date& operator++();
// 后置++
Date operator++(int);
// 前置--
Date& operator--();
// 后置++
Date operator--(int);
下面是代码实现,代码比较长,请耐心看完,在代码中我作了详细的解释,有什么疑问可以留言联系。
#include <iostream>
using namespace std;
class Date
{
public:
Date()
{}
Date(int year,int month,int day)
:_year(year)
, _month(month)
, _day(day)
{
if (!(year > 0 && (month > 0 && month < 13) && day>0 && day < GetMonthDays(year, month)))
{
cout << "日期非法!" << endl;
}
}
// 当前日期days天后是什么日期?
Date operator+(int days)
{
if (days < 0)
{
return (*this) - (0 - days); //如果要加上的数为负数的处理办法,就让当前对象减去这个负数
}
int DaysInMonth = 0;
Date temp(*this);
temp._day += days;
while (temp._day >(DaysInMonth = GetMonthDays(temp._year, temp._month))) //检测加完之后的日期是否合法
{
temp._day -= DaysInMonth;
temp._month++;
if (temp._month > 12)
{
temp._year += 1;
temp._month = 1;
}
}
return temp;
}
//// 当前日期days天前是什么日期?
Date operator-(int days)
{
if (days < 0)
{
return *this + (0 - days); //如果要减上的数为负数的处理办法,就让当前对象加上这个负数
}
Date temp(*this);
temp._day -= days;
while (temp._day <= 0)
{
temp._month -= 1;
if (0 == temp._month)
{
temp._year -= 1;
temp._month = 12;
}
temp._day += GetMonthDays(temp._year, temp._month);
}
return temp;
}
// 两个日期之间差了多少天?
int operator-(const Date& d)
{
Date minDate(*this);
Date maxDate(d);
if (minDate > maxDate)
{
minDate = d;
maxDate = *this;
}
int count = 0;
while (minDate != maxDate)
{
count++;
++minDate;
}
return count;
}
// 日期比大小
bool operator>(const Date& d)
{
if (_year > d._year ||
_year == d._year && _month > d._month ||
_year == d._year && _month == d._month && _day > d._day)
{
return true;
}
return false;
}
bool operator<(const Date& d)
{
if (_year < d._year ||
_year == d._year && _month < d._month ||
_year == d._year && _month == d._month && _day < d._day)
{
return true;
}
else
return false;
}
//判断两个日期是否相等
bool operator==(const Date& d)
{
return _year == d._year && _month == d._month && _day == d._day;
}
bool operator!=(const Date& d)
{
return !(*this == d);
}
//为了实现连续赋值,因此要有返回值,为了效率高,因此给引用
Date& operator=(const Date& d)
{
if (this != &d) //检测是不是自己给自己赋值
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
// 重载取地址符号
Date* operator&()
{
return this;
}
// 前置++
Date& operator++()
{
_day += 1;
return *this;
}
// 后置++ ,返回的是保存之前的旧值
Date operator++(int)
{
Date temp(*this);
_day += 1;
return temp;
}
// 前置--
Date& operator--()
{
_day -= 1;
return *this;
}
// 后置--
Date operator--(int)
{
Date temp(*this);
_day -= 1;
return temp;
}
friend ostream& operator<<(ostream& _cout, const Date& d)
{
_cout << d._year << "/" << d._month << "/" << d._day;
return _cout;
}
bool IsLeapyYear(int year) //判断是不是闰年
{
if ((0 == year % 4 && 0 != year % 100) || (0 == year % 400))
return true;
else
return false;
}
private:
int GetMonthDays(int year, int month)
{
int DayOfMonth[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; //每个月的天数
//先判断是不是二月
if (2 == month && IsLeapyYear(year))
{
DayOfMonth[month] += 1;
}
return DayOfMonth[month];
}
//日期类的析构函数没有任何作用,因此这里不用给出析构函数,因为当前对象并没有管理任何资源
private:
int _year;
int _month;
int _day;
};
void TestDate()
{
Date d1(2018, 8, 4);
Date d2;
d2 = d1;
d2 = d1 + 100;
cout << d2 << endl;
}
//现在我们假设一个场景:假如现在我们想要知道100天以后是几号,那么我们应该怎么做呢?
int main()
{
TestDate();
//我们可能会想到在这个日期类直接加上100不就好了,事实真是这样么?显然,编译报错了(这里自己上机实验),说明这样做是不可取的。
//d1+100;
//下面的代码是边完善日期类写的测试,感兴趣可以自己上机实验
#if 0
Date d1(2018, 8, 4);
Date d2(d1);
d2.PrintDate();
Date d3(2018, 8, 5);
Date& d4 = d1;
d3++;
++d3;
d2 = d1; // 这句话可以理解为 d2.operator=(d1);====> Date::operator=(&d2,&d1)
d2 = d1 + 100;
#endif
return 0;
}
这里给出部分检测结果: