在上篇博客中我们已经学习了C++中的运算符重载,我们说,操作符只能对于内置类型进行操作,对自定义类型我们需要自己定义函数去实现一系列的操作
那么这篇博客我们就专门把日期这个类单独拿出来写一下它都有哪些有意义的可以重载的运算符,这个函数我们要放到类里面为了访问私有的成员变量,但是函数声明和定义可以分到两个文件中写,只需要标识一下它属于哪个类就行。还有我们之前说过的一点,缺省参数只能声明给,定义不用给,因为编译器怕你给的不一样。
下面一个类当中首先是成员变量年月日我就不说了,下面是构造函数,我们就写一个全缺省的函数,默认不传参数年月日都是一,但是我们要判断传过来的数字是否合法,不合法要做出提醒,可以assert断言,也可以就打印一下。
//声明
Date(int year = 1, int month = 1, int day = 1);
//定义
Date::Date(int year, int month , int day ) {
_year = year;
_month = month;
_day = day;
if (_year < 1 || _month < 1 || _month>12 || _day<1 || _day>GetMonthDay(_year, _month)) {
cout << _year << "年" << _month << "月" << _day << "日";
cout << "日期非法" << endl;
}
}
下面比较两个日期的大小和是否相等其实逻辑就比较简单了,写上一个后边的直接赋用就行
比如说
bool Date:: operator==(const Date& n) {
return _year == n._year && _month == n._month && _day == n._day;
}
bool Date::operator!=(const Date& n) {
return !(*this == n);
}
写了等于那么不等于不就是它的相反嘛
下面的大于小于也是同理
bool Date:: operator<(const Date& n) {
if (_year < n._year) {
return true;
}
if (_year == n._year && _month < n._month) {
return true;
}
if (_year == n._year && _month == n._month && _day < n._day) {
return true;
}
return false;
}
bool Date::operator<=(const Date& n) {
return ((*this < n) || (*this == n));
}
bool Date::operator>(const Date& n) {
return !(*this <= n);
}
bool Date:: operator>=(const Date& n) {
//return *this > n || *this == n;
return !(*this < n);
}
下面是加减运算,首先日期加日期是没有意义的,但是日期加减天数是有意义的,这个该如何去加减呢?我们可以先把天数加到年月日的日数上,如果合法就不用动了,如果多余本月的该有的天数就进位到月上。为了方便就得有一个得到该年该月的天数的一个函数
int Date :: GetMonthDay(int year, int month) {
assert(year >= 1 && month >= 1 && month <= 12);
int monthArray[13] = { 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 monthArray[month];
}
下边就是日期加减一个天数
Date& Date:: operator+=(int day) {
if (day < 0) {
return *this -= (-day);
}
_day += day;
while (_day > GetMonthDay(_year, _month)) {
_day -= GetMonthDay(_year, _month);
++_month;
if (_month == 13) {
++_year;
_month = 1;
}
}
return *this;
}
Date Date:: operator+(int day) {
Date tmp(*this);
tmp += day;
return tmp;
}
Date& Date:: operator-=(int day) {
if (day < 0) {
return *this += (-day);
}
_day -= day;
while (_day <= 0) {
--_month;
if (_month == 0) {
--_year;
_month = 12;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
Date Date:: operator-(int day) {
Date tmp(*this);
tmp -= day;
return tmp;
}
我这里的加减是赋用的加等和减等,当然了我们也可以让加等和减等赋用加减,我们也来实现一下,然后看看这两种情况哪个好
Date Date:: operator+(int day) {
Date tmp=*this;
tmp._day += day;
while (tmp._day > GetMonthDay(tmp._year, tmp._month)) {
tmp._day -= GetMonthDay(tmp._year, tmp._month);
tmp._month++;
if (tmp._month == 13) {
++tmp._year;
tmp._month = 1;
}
}
return tmp;
}
Date& Date:: operator+=(int day) {
*this = *this + day;
return *this;
}
Date Date::operator-(int day) {
Date tmp(*this);
tmp._day -= day;
while (tmp._day <= 0) {
--tmp._month;
if (tmp._month == 0) {
tmp._year--;
tmp._month = 12;
}
tmp._day += GetMonthDay(tmp._year, tmp._month);
}
return tmp;
}
Date& Date:: operator-=(int day) {
*this = *this - day;
return *this;
}
我们先看第一种情况,加等其实是不需要进行拷贝的,而加则需要拷贝两次。第二种情况,加要拷贝两次,而加等要拷贝三次,所以我们可以看出第一种情况更好一些
我们这里的加等还有一个问题,如果我们写的是加等一个负数或者说减等一个负数时就会有问题,这时就会有问题,我们只需要转到相反的就行了,就类似这样:
Date& Date:: operator-=(int day) {
if (day < 0) {
return *this -= (-day);
}
下面就是++了,但是++有前置,有后置,这时我们就规定后置++要在形参上写上一个int,写别的不行
Date& Date::operator++() {
*this += 1;
return *this;
}
Date Date:: operator++(int) {
Date tmp(*this);
*this += 1;
return tmp;
}
Date& Date::operator--() {
*this -= 1;
return *this;
}
Date Date:: operator--(int) {
Date tmp(*this);
*this -= 1;
return tmp;
}
下面的日期减日期也是有意义的,就是相差的天数
简单的话就是从小的日期一直加直到大的日期,看一共加了多少回
int Date::operator-(const Date& d) {
int flag = -1;
Date min = *this;
Date max = d;
if (*this > d) {
min = d;
max = *this;
flag = 1;
}
int n = 0;
while (min < max) {
++min;
++n;
}
return n*flag;
}
要想效率更高些就要整年整年的加,后面的零碎的天数就从1月1日开始数,大的日期就加上,小的日期就减去
int Date::operator-(const Date& d) {
int flag = 1;
Date max = *this;
Date min = d;
if (*this < d) {
max = d;
min = *this;
flag = -1;
}
int n = 0;
int y = min._year;
while (y != max._year) {
if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) {
n += 366;
}
else {
n += 365;
}
y++;
}
int m1 = 1;
int m2 = 1;
while (m1 < max._month) {
n += GetMonthDay(max._year, m1);
m1++;
}
while (m2 < min._month) {
n -= GetMonthDay(min._year, m2);
m2++;
}
n = n + max._day - min._day;
return n;
}
下面是Date.h中所有代码
#include
#include
using namespace std;
class Date {
public:
Date(int year = 1, int month = 1, int day = 1);
void Print();
int GetMonthDay(int year, int month);
bool operator==(const Date& n);
bool operator!=(const Date& n);
bool operator<(const Date& n);
bool operator<=(const Date& n);
bool operator>(const Date& n);
bool operator>=(const Date& n);
Date& operator+=(int day);
Date operator+(int day);
Date& operator-=(int day);
Date operator-(int day);
Date& operator++();//前置++
Date operator++(int);//后置++
Date& operator--();
Date operator--(int);
int operator-(const Date& d);
private:
int _year;
int _month;
int _day;
};
Date.cpp文件中的代码
#include"Date.h"
Date::Date(int year, int month , int day ) {
_year = year;
_month = month;
_day = day;
if (_year < 1 || _month < 1 || _month>12 || _day<1 || _day>GetMonthDay(_year, _month)) {
cout << _year << "年" << _month << "月" << _day << "日";
cout << "日期非法" << endl;
}
}
void Date::Print() {
cout << _year << "年" << _month << "月" << _day << "日" << endl;
}
int Date :: GetMonthDay(int year, int month) {
assert(year >= 1 && month >= 1 && month <= 12);
int monthArray[13] = { 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 monthArray[month];
}
bool Date:: operator==(const Date& n) {
return _year == n._year && _month == n._month && _day == n._day;
}
bool Date::operator!=(const Date& n) {
return !(*this == n);
}
bool Date:: operator<(const Date& n) {
if (_year < n._year) {
return true;
}
if (_year == n._year && _month < n._month) {
return true;
}
if (_year == n._year && _month == n._month && _day < n._day) {
return true;
}
return false;
}
bool Date::operator<=(const Date& n) {
return ((*this < n) || (*this == n));
}
bool Date::operator>(const Date& n) {
return !(*this <= n);
}
bool Date:: operator>=(const Date& n) {
//return *this > n || *this == n;
return !(*this < n);
}
Date& Date:: operator+=(int day) {
if (day < 0) {
return *this -= (-day);
}
if (day < 0) {
return *this -= (-day);
}
_day += day;
while (_day > GetMonthDay(_year, _month)) {
_day -= GetMonthDay(_year, _month);
++_month;
if (_month == 13) {
++_year;
_month = 1;
}
}
return *this;
}
Date Date:: operator+(int day) {
Date tmp(*this);
tmp += day;
return tmp;
}
Date& Date:: operator-=(int day) {
if (day < 0) {
return *this -= (-day);
}
if (day < 0) {
return *this += (-day);
}
_day -= day;
while (_day <= 0) {
--_month;
if (_month == 0) {
--_year;
_month = 12;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
Date Date:: operator-(int day) {
Date tmp(*this);
tmp -= day;
return tmp;
}
Date& Date::operator++() {
*this += 1;
return *this;
}
Date Date:: operator++(int) {
Date tmp(*this);
*this += 1;
return tmp;
}
Date& Date::operator--() {
*this -= 1;
return *this;
}
Date Date:: operator--(int) {
Date tmp(*this);
*this -= 1;
return tmp;
}
//int Date::operator-(const Date& d) {
// int flag = -1;
// Date min = *this;
// Date max = d;
// if (*this > d) {
// min = d;
// max = *this;
// flag = 1;
// }
// int n = 0;
// while (min < max) {
// ++min;
// ++n;
// }
// return n*flag;
//}
int Date::operator-(const Date& d) {
int flag = 1;
Date max = *this;
Date min = d;
if (*this < d) {
max = d;
min = *this;
flag = -1;
}
int n = 0;
int y = min._year;
while (y != max._year) {
if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) {
n += 366;
}
else {
n += 365;
}
y++;
}
int m1 = 1;
int m2 = 1;
while (m1 < max._month) {
n += GetMonthDay(max._year, m1);
m1++;
}
while (m2 < min._month) {
n -= GetMonthDay(min._year, m2);
m2++;
}
n = n + max._day - min._day;
return n;
}