为了实现一个类,我们通常需要以下几个步骤:
构造函数就简单利用初始化列表进行初始化,并且加断言保证日期创建合法。
注意:构造函数可以给缺省值但是由于声明和定义分离,缺省值只能给其中一个,一般建议写在声明时。
Date::Date(int year, int month, int day )
:_year(year)
, _month(month)
, _day(day)
{
assert(year > 0
|| month > 0 || month < 13
|| day>0 || day <= GetMonth_day());
}
日期类没有复杂的资源申请和释放可以不用写析构函数和拷贝构造函数(也可以写),系统自动生成的就够用了。
为了方便进行控制台的输出和输入,我们先把流插入和流提取的运算符进行重载。
因为流插入和流提取是双目运算符,且左操作数(第一个形参)是流对象,而一般情况下,在类内定义的函数形参第一位有个默认的this指针,所以我们不能直接在类内定义,而要在类外定义,再使用友元关键字(friend)进行声明,即可在类外定义可以访问类内成员的函数。
声明:
//流插入和流提取运算符重载
friend std::istream& operator>>(std::istream& in, Date& d);
friend std::ostream& operator<<(std::ostream& out, const Date& d);
定义
std::istream& operator>>(std::istream& in, Date& d)
{
in >> d._year >> d._month >> d._day;
return in;
}
std::ostream& operator<<(std::ostream& out, const Date& d)
{
out<< d._year <<"年"<< d._month <<"月"<< d._day<<"日";
return out;
}
先写流插入(<<)和流提取(>>)运算符重载还可以方便调试。
Date& Date::operator=(const Date& d1)
{
_year = d1._year;
_month = d1._month;
_day = d1._day;
return *this;
}
比较运算符只需要写出两个即可,其余的可以直接进行复用。
可以直接列举所有符合小于的情形,返回true;
最后以上情形都不符合,返回false;
bool Date::operator<(Date& d)
{
if (_year < d._year)
return true;
else if (_year == d._year && _month < d._month)
return true;
else if (_year == d._year && _month == d._month && _day < d._day)
return true;
return false;
}
也可以进行简化
if( (_year < d._year)||
(_year == d._year && _month < d._month)||
(_year == d._year && _month == d._month && _day < d._day))
return true;
return false;
直接判断年月日是否都相等
bool Date::operator==(Date& d)
{
if (_year == d._year && _month == d._month && _day == d._day)
return true;
return false;
}
其它比较运算符均可以复用上面两个运算符
bool Date::operator>(Date& d)
{
return d < *this;
}
bool Date::operator!=(Date& d)
{
return !(d == *this);
}
bool Date::operator>=(Date& d)
{
return !(*this<d);
}
bool Date::operator<=(Date& d)
{
return !(*this > d);
}
算术运算符中乘除没有用,日期加日期没有意义,所以有意义可以实现的有:
日期加减天数(+、-),日期加等于、减等于天数(+=、-=),日期减日期(-),日期的++和–
而且只需要写出加等即可,其余的可以直接进行复用。(也可以实现其他任意一个,其余复用它。不过其余复用加等的方式效率最好)
直接将天数加到类内的_day 上
首先如果考虑到加等的天数可以为负数,则需要先进行判断天数的正负,再进行其他操作。
然后使用循环不断将_day 修正到合法范围里(其中的GetMonth_day()是获取当月最大天数的函数)
Date& Date::operator+=(int day)
{
_day += day;
if (day > 0)//day为正数
{
while (_day >= Date::GetMonth_day())
{
_day -= Date::GetMonth_day();
++_month;
if (_month > 12)
{
_month = 1;
++_year;
}
}
}
else//day为负数
{
while (_day < 1)
{
_day += GetMonth_day();
--_month;
if (_month == 0)
{
--_year;
assert(_year > 0);
_month = 12;
}
}
}
return *this;
}
这几个运算符可以直接复用加等或相互复用
Date Date::operator+(int day) const
{
Date tmp = *this;
tmp += day;
return tmp;
}
Date& Date::operator-=(int day)
{
*this += (-day);
return *this;
}
Date Date::operator-(int day)const
{
Date tmp(*this);
tmp -= day;
return tmp;
}
前置++和前置–为了和后置++、后置–区分,加了一个没有实际意义的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-(Date& d)
{
int count = 0;
int flag = 1;//假设*this >= d
if (*this < d)//修正
flag = -1;
while (d + count != *this)
{
count += flag;
}
return count;
}
最终实现的效果如下:
下面是日期类的声明,一般放在.h文件
//Date.h
#include
#include
class Date
{
public:
int GetMonth_day();
//
Date(int year = 1, int month = 1, int day = 1);
Date(const Date& d1);
~Date();
//流插入和流提取运算符重载
friend std::istream& operator>>(std::istream& in, Date& d);
friend std::ostream& operator<<(std::ostream& out, const Date& d);
//赋值运算符重载
Date& operator=(const Date& d1);
//比较运算符重载
bool operator>(Date& d);
bool operator<(Date& d);
bool operator==(Date& d);
bool operator!=(Date& d);
bool operator>=(Date& d);
bool operator<=(Date& d);
//日期加法相关运算符重载
Date& operator+=(int day);
Date operator+(int day) const;
Date& operator++();//前置++
Date operator++(int);//后置++
//日期减法相关运算符重载
Date& operator-=(int day);
Date operator-(int day)const;
Date& operator--();//前置--
Date operator--(int);//后置--
//日期减日期
int operator-(Date& d);
private:
int _year;
int _month;
int _day;
};
下面是日期类的定义,一般放在.cpp文件
#include"Date.h"
Date::Date(int year, int month, int day )
:_year(year)
, _month(month)
, _day(day)
{
assert(year > 0||
month > 0 || month < 13||
day>0 || day <= GetMonth_day());
}
Date::Date(const Date& d1)
{
_year = d1._year;
_month = d1._month;
_day = d1._day;
}
Date::~Date()
{
//资源释放
}
int Date::GetMonth_day()
{
int n[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
int day = n[_month];
if (_month == 2 && ((_year % 4 == 0) && (_year % 100 != 0 || _year % 400 == 0)))//是否为闰年
++day;
return day;
}
std::istream& operator>>(std::istream& in, Date& d)
{
in >> d._year >> d._month >> d._day;
return in;
}
std::ostream& operator<<(std::ostream& out, const Date& d)
{
out<< d._year <<"年"<< d._month <<"月"<< d._day<<"日";
return out;
}
Date& Date::operator=(const Date& d1)
{
_year = d1._year;
_month = d1._month;
_day = d1._day;
return *this;
}
Date& Date::operator+=(int day)
{
if (day > 0)//day为正数
{
_day += day;
while (_day >= Date::GetMonth_day())
{
_day -= Date::GetMonth_day();
++_month;
if (_month > 12)
{
_month = 1;
++_year;
}
}
}
else//day为负数
{
_day += day;
while (_day < 1)
{
_day += GetMonth_day();
--_month;
if (_month == 0)
{
--_year;
assert(_year > 0);
_month = 12;
}
}
}
return *this;
}
Date Date::operator+(int day) const
{
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-=(int day)
{
*this += (-day);
return *this;
}
Date Date::operator-(int day)const
{
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;
}
bool Date::operator==(Date& d)
{
if (_year == d._year && _month == d._month && _day == d._day)
return true;
return false;
}
bool Date::operator<(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 Date::operator>(Date& d)
{
return d < *this;
}
bool Date::operator!=(Date& d)
{
return !(d == *this);
}
bool Date::operator>=(Date& d)
{
return !(*this<d);
}
bool Date::operator<=(Date& d)
{
return !(*this > d);
}
int Date::operator-(Date& d)
{
int count = 0;
int flag = 1;
if (*this < d)
flag = -1;
while (d + count != *this)
{
count += flag;
}
return count;
}