目录
获取月份天数采用了静态数组的方式。由于数组下标是从0开始的,为了使月份与下标一一对应,开13个int大小的数组。但是下标为0的位置随便存入一个0,用来占位。之后表示出对应月份对应的天数。
如果是闰年的话,那么这一年的月份还要+1;
由于他被频繁调用,所以我把他写在函数的内部,当做内联函数来提高效率。
- int GetMonthDay(int year, int month)
- {
- int monthday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
- if (year % 400 == 0 || year % 4 == 0 && year % 100 != 0)
- {
- monthday[2] += 1;
- }
- return monthday[month];
- }
全缺省构造函数其实就是在写构造函数的时候,给年月日都定下对应的缺省值。
- Date(int year = 1, int month = 1, int day = 1)
- {
- _year = year;
- _month = month;
- _day = day;
- }//全缺省构造函数
拷贝构造函数传入对应的日期类。注意必须要传入引用。否则会产生无穷递归。
- Date(Date const& date)
- {
- _year = date._year;
- _month = date._month;
- _day = date._day;
- }//拷贝构造函数
日期类的析构函数可有可无。因为日期类并没有对应的资源需要清理。但是即使这样,我们不写,编译器也会自动生成一个析构函数。只不过这个析构函数什么事情都不需要做。但是它确确实实被调用了。
- ~Date()
- {
-
- }//析构函数
运算符重载的话,其实只用实现==和<或者==和>即可。因为其他的运算符重载去复用写好的就可以实现了。比如实现<=,那么逻辑上就是>的逻辑取反并且满足==。
- bool operator==(const Date& date)const
- {
- return _year == date._year
- && _month == date._month
- && _day == date._day;
- }
- bool operator!=(const Date& date)const
- {
- return !(*this == date);
- }
- bool operator>(const Date& date)const
- {
- if (_year > date._year)
- {
- return true;
- }
- else if (_year == date._year && _month > date._month)
- {
- return true;
- }
- else if (_year == date._year && _month == date._month && _day > date._day)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- bool operator>=(const Date& date)const
- {
- return(*this > date && *this == date);
- }
- bool operator<(const Date& date)const
- {
- return !(*this >= date);
- }
- bool operator<=(const Date& date)const
- {
- return (*this < date && *this == date);
- }
赋值运算符的重载可以使用引用传参,并且由于不需要对传入的参数做修改,因此可以用const来修饰。由于返回的是被赋值重载后的*this。不会被销毁。因此也可以用引用返回来提高效率。
- Date& operator=(const Date& date)
- {
- _year = date._year;
- _month = date._month;
- _day = date._day;
- return *this;
- }//赋值重载
①+=思路是进位。首先全部加在日上面,再去进位。进位的规则:如果日期不合法,比如日大于当月的最大天数,那么就需要向月份上面进位。如果月份也大于这一年中的最大月份。那么就向年来进位。
注意的是,当月份向年进位的时候,同时月份也会被置成1.
- Date&operator+=(int day)
- {
- if (day < 0)
- {
- return *this -= -day;
- }
- _day += day;
- while(_day > GetMonthDay(_year, _month))
- {
- _day -= GetMonthDay(_year, _month);
- _month+=1;
- if (_month > 12)
- {
- _year += 1;
- _month = 1;
- }
- }
- return *this;
- }
②+
由于+的话,不会对*this产生修改,因此需要用一个临时变量来完成上述的操作,并且返回这个临时变量。
其他代码的实现也可以直接复用
- Date operator+(int day)
- {
- Date ret(*this);
- ret += day;
- return ret;
- }
①-=
与+=的思路相反。不过要注意的是,需要先判断月份是否合法,再把借到的上一个月的天数加到当月。否则,如果是一月份不合法,借位,借到的就是0月的天数了。
- Date& operator-=(int day)
- {
- if (day < 0)
- {
- return *this += -day;
- }
- _day -= day;
- while (_day<1)
- {
- _month -= 1;
- if (_month < 1)
- {
- _year -= 1;
- _month = 12;
- }
- _day += GetMonthDay(_year, _month);//要先判断 因为是借上一年的 如果不判断的话 1月份的天数是负数的情况此时借位加不上去 还需要向年借
-
- }
- return *this;
- }
②-
和上述一样去复用即可。
- Date operator-(int day)
- {
- Date ret(*this);
- return ret -= day;
- }
为什么用-=和+=来复用-和+?
如果反着来的话,需要实现很多次拷贝构造,会降低效率。
①前置++
前置++返回的是++前的值,并且本身也会被修改。因此需要用临时变量保存++前的值,并且返回这个临时变量。因此返回值不能用引用。前置++参数列表带int可以不传参,主要是为了与后置++相区分
- Date operator++(int)
- {
- Date ret(*this);
- *this += 1;
- return ret;
- }
②后置++
后置++返回++之后的值,因此直接返回即可。
- Date& operator++()
- {
- return *this +=1;
- }
前置--与后置--逻辑和上述的实现差不多。
不做过多的阐述了。
- Date& operator--()
- {
- return *this -= 1;
- }
- Date operator--(int)
- {
-
- Date ret(*this);
- *this -= 1;
- return ret;
- }
思路:主要是得出二者较小的天数的日期,用计数器来计算两者之间的相差天数。
flag是为了实现正负。默认第一个日期类型比第二个日期类型要大。flag为正。但是如果与猜想相反的话,大小日期和flag都需要重置。
- int operator-( const Date&date)const
- {
- int flag = 1;
- Date min = date;
- Date max = *this;
- if (*this >date)
- {
- max = date;
- min = *this;
- flag = -1;
- }
-
- int count = 0;
- while (min != max)
- {
- count++;
- min++;
- }
- return count * flag;
-
-
- }