接上文来完整实现日期类的成员函数,先是日期类的成员变量
class Date
{
public:
private:
int _year:
int _month;
int _day;
}
在写日期类的默认成员函数和运算符重载之前,我们先写一个函数来获得某年某年某月的具体天数,我们定义一个静态数组monthDayArray[]去记录每个月的天数,如果是闰年的二月就返回二十九天,其他情况下返回monthDayArray[month]
int GetMonthDay(int year, int month)
{
assert(year >= 0 && month >= 0 && month <= 12);
static int monthDayArray[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
if (month == 2 && isLeapYear(year))
return 29;
else
return monthDayArray[month];
}
这里面还有一个判断闰年的函数要去实现,这个大家应该都会
bool isLeapYear(int year)
{
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
接下来实现日期类的构造函数,也就是把我们输入的年月日赋值给日期对象,需要注意的是我们输入的数据需要是一个有效的日期,我们需要对这个年月日进行检查,年要大于零,月大于零小于等于十二,日大于零小于等于当月最大天数
Date(int year = 1970, int month = 1, int day = 1)
{
if (year > 0 && (month > 0 && month < 13) && (day > 0 && day <= GetMonthDay(year,month)))
{
_year = year;
_month = month;
_day = day;
}
else
cout << "非法参数" << endl;
}
拷贝构造就很简单了,对年月日进行赋值即可
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
接下来就是赋值运算符的重载,按照难易顺序来,先来一个==的重载
bool operator==(const Date& d)
{
return ((_year == d._year) && (_month == d._month) && (_day == d._day));
}
与==相反的是!=,一开始我想的是年不相等或月不相等或日不想等则返回true,但是我们上面已经写了==了,为什么不能把==用起来呢,!=就是==取反,这个思路也让我们下面实现起来更简单
bool operator!=(const Date& d)
{
return !(*this == d);
}
接下来我们实现<,按照我们上面的思路,我们实现了<也就间接实现了>=,因为<本就与>=对立,<我的实现思路和我们数学上整型比大小类似,我们可以把日期类的对象看成是一个三位数,先比百位,百位相等就去比十位,以此类推
bool operator<(const Date& d)
{
if (_year == d._year)
{
if (_month == d._month)
{
return _day < d._day;
}
return _month < d._month;
}
else
return _year < d._year;
}
那>=就是<取反了
bool operator>=(const Date & d)
{
return !(*this < d);
}
>和<=和上面类似,我就只贴代码了
bool operator>(const Date& d)
{
if (_year == d._year)
{
if (_month == d._month)
{
return _day > d._day;
}
return _month > d._month;
}
else
return _year > d._year;
}
bool operator<=(const Date& d)
{
return !(*this > d);
}
接下来我们实现+,当然+也有加上多少多少天和加上另一个日期类,我认为日期加日期没有意义,因此就只实现日期加天数,日期加天数是要有返回值的,但是又不能在*this上直接操作,就像是c=a+10;我们的a并不会改变,a不会变成a+10,怎么做呢,我们用拷贝构造创建一个临时对象,在这个临时对象上操作并返回它
至于逻辑实现我们可以把它理解为十进制相加的进位一样,先把天数加到_day里,如果_day大于那个月的天数就进位,月大于十二就进位
Date operator+(int day)
{
Date temp(*this);
temp._day = temp._day + day;
while (temp._day > GetMonthDay(temp._year, temp._month))
{
temp._day = temp._day - GetMonthDay(temp._year, temp._month);
temp._month = temp._month + 1;
if (temp._month > 12)
{
temp._month = 1;
temp._year = temp._year + 1;
}
}
return temp;
}
+=和+的区别就是+=是加在*this上的,返回的是*this
Date operator+(int day)
{
Date temp(*this);
temp._day = temp._day + day;
while (temp._day > GetMonthDay(temp._year, temp._month))
{
temp._day = temp._day - GetMonthDay(temp._year, temp._month);
temp._month = temp._month + 1;
if (temp._month > 12)
{
temp._month = 1;
temp._year = temp._year + 1;
}
}
return temp;
}
-和-=的实现逻辑和上面的类似,也只贴代码了
Date operator-(int day)
{
Date temp(*this);
temp._day = temp._day - day;
while (temp._day <=0)
{
temp._month = temp._month - 1;
if (temp._month == 0)
{
temp._month = 12;
temp._year = temp._year - 1;
}
temp._day = temp._day + GetMonthDay(temp._year, temp._month);
}
return temp;
}
Date& operator-=(int day)
{
*this = *this - day;
return *this;
}
当然还有前后置的自加和自减,有两个问题,一是怎么区分前后置,还有就是前后置的具体实现,如何区别前后置c++已经给了我们解决方案,那就是前置++没有参数,而后置++的参数为(int),那么怎么去实现前置和后置,也就是先自加再运算和先运算再自加,在后置我们可以直接加如何返回,前置只需要对*this进行拷贝,然后*this自加,返回拷贝
Date& operator++()
{
*this += 1;
return *this;
}
Date operator++(int)
{
Date tmp(*this);
*this += 1;
return tmp;
}
Date& operator--()
{
*this -= 1;
return *this;
}
Date operator--(int)
{
Date tmp(*this);
*this -= 1;
return tmp;
}
Date operator=(const Date& d)
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}