前言
1.日期类是一种十分经典的类型。对于C++的初学者,它能够帮助我们融会贯通许多C++的基础知识,它涉及许多的基础语法,比如引用,函数重载,传值/传参返回,构造函数,运算符重载,const成员等等。
如果有不了解的,可以前往我的主页浏览相关文章。
日期计算器可以实现两个日期的比较,两个日期的相减,日期的加减天数等有意义的运算。
2.本文依然采用多文件方式。其中:
Date.h //定义类,存放各函数的声明;
Date.cpp //实现各重载函数;
Test.cpp //测试各函数的功能。
在C++中,由于函数的声明与定义分离,如果要定义成员函数,就要指定类域,这是基本语法。
一,各个函数功能的实现
1. 检查输入的日期是否合法
不管是日期的比较还是日期的运算,第一步都要检查日期的合法性。特别是月份和每个月的天数。
代码实现如下:
bool Date::CheakDate()
{
if (_month < 1 || _month>12
|| _day<1 || _day>GetMonthDay(_year, _month))
{
return false;
}
else
{
return true;
}
}
2. 构造函数 (初始化函数)
为了方便,在使用默认构造函数时,一般是自己显式的实现一个全缺省构造函数。
注意:
在函数的声明和定义分离时,如果要给缺省值,必须在函数声明的时候给。
代码实现如下:
Date::Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
//日期的源头,是从构造函数里出来的,所以要在这里判断
if (!CheakDate())
{
cout << "日期非法!" << endl;
}
}
二,比较类的运算符重载
3. <运算符重载
判断两个日期谁更小。思路:先比年,年小就小,年相等比月,月小就小,年月相等比日,日小就小。
代码实现如下:
d1 < d2 隐含的this指针是d1,d是d2的别名。
bool Date::operator< (const Date& d) const
{
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;
}
4. ==运算符重载
判断两个日期是否相等 。这个比较简单,如果两者的年月日都相等,即相等。
代码实现如下:
bool Date::operator==(const Date& d) const
{
return _year == d._year
&& _month == d._month
&& _day == d._day;
}
5. >=运算符重载
有人可能会仿照<运算符重载的方法,使用复杂的逻辑,写各种晦涩的代码实现。其实只要实现了<运算符重载和==运算符重载,下面的日期比较类都是可以复用的。 比如这里的>=,< 取反就是>=。
代码实现如下:
bool Date::operator>= (const Date& d) const
{
return !(*this < d);
}
6. >运算符重载
<= 取反,就是>。
bool Date::operator> (const Date& d) const
{
return !(*this <= d);
}
7. <=运算符重载
只要满足<或者=,就是<=。
bool Date::operator<= (const Date& d) const
{
return *this < d || *this == d;
}
8. !=运算符重载
==去取反,就是!=。
bool Date::operator!=(const Date& d) const
{
return !(*this == d);
}
9. 获取某月的天数
这个函数是整个日期类的关键,也是最频繁调用的一个函数。由于这个原因,最好把它定义成内联函数,避免每次调用都要开辟空间,可以提升效率。根据C++的语法,定义在类里默认是内联,inline可加可不加。
代码实现如下:
这里还有两个优化的细节:
1. month == 2 和后面的取模运算的位置。首先满足是2月,再判断是否是闰年,效率会更高。
2. static的使用,由于该函数频繁调用,把数组放在静态区,避免每次调用函数时每次都要开辟数组空间。
int GetMonthDay(int year, int month)
{
//断言,确保输入月份的有效性
assert(month > 0 && month < 13);
//枚举出月份的天数
static int monthDayArray[13] = {
-1, 31,28,31,30,31,30,31,31,30,31,30,31 };
//判断2月的平年和闰年