前言:实现一个完整的日期类,来加强对这类的6个默认成员函数的认识。
目录
构造函数
GetMonthDay函数中的三个细节:
打印函数
日期 += 天数
日期 + 天数
日期 -= 天数
日期 - 天数
前置 ++
后置 ++
前置 --
后置 --
日期类的大小关系比较
>运算符的重载
==运算符的重载
<运算符的重载
>=运算符的重载
<=运算符的重载
!=运算符的重载
日期 - 日期
今天星期几
日期类中所包含的成员函数和成员变量:
class Data
{
public:
//构造函数
Data(int year = 0, int month = 1, int day = 1);//赋值运算符的重载
Data& operator=(const Data& d);//+=运算符的重载
Data& operator+=(int day);
//获得此年此月的天数
int GetMonthDay(int year, int month)const;
//+运算符的重载
Data operator+(int day)const;//前置++重载
Data& operator++();//后置++重载
Data operator++(int);//-=运算符的重载
Data& operator-=(int day);//-运算符的重载
Data operator-(int day)const;//重载前置--
Data& operator--();
//后置--重载
Data operator--(int);//>运算符重载
bool operator>(const Data& d)const;//运算符==重载
bool operator==(const Data& d)const;//运算符>=重载
bool operator<=(const Data& d)const;//运算符<重载
bool operator<(const Data& d)const;//运算符<=重载
bool operator>=(const Data& d)const;//运算符!=重载
bool operator!=(const Data& d)const;//日期-日期
int operator-(const Data& d)const;//今天是星期几
void IsWeekDay()const;//打印日期
void Print()const;
private:
int _year;
int _month;
int _day;
};
析构,拷贝构造,赋值重载可以不写,使用默认生成的即可
构造函数
对象创建时,进行对象变量的赋值,需要先判断日期是否合理,进行后续构造。
因为函数声明(.h)与定义(.cpp)分离,所以定义需要指定函数的类域 类名::+函数名
int Data::GetMonthDay(int year, int month)const
{//数组存储平年每个月的天数
const int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
int day = days[month];
if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
{
day += 1;//闰年二月的天数是29
}
return day;
}Data::Data(int year, int month, int day)
{//判断日期是否合理之后进行赋值
if (year >= 0 &&month > 0 && month < 13
&& day>0 && day <= GetMonthDay(year, month))
{
_year = year;
_month = month;
_day = day;
}
else
{
cout << "日期非法:";
cout << _year << "-" << _month << "-" << _day << endl;
}
}
GetMonthDay函数中的三个细节:
1.用const修饰this指针,因为this不能被修改。
2.days数组最好用static修饰,这样在静态区存储,不会因为频繁调用而频繁创建。
3.判断平年还是闰年的天数时,先判断是否是二月,在进行平闰年的判断。
注:当函数声明和定义分开时,在声明时注明缺省参数,定义时就不能标出缺省参数。
打印函数
void Data::Print()const
{
cout << _year << "年" << _month << "月" << _day << "日" << endl;
}
日期 += 天数
+=操作符,会改变对象变量的值。
实现思路:1.日期对象的天数加上天数 2.判断日期是否合理,若不合理(表示日满),天数-=这年这月的天数,然后月份month++,若month>12时,year++,month重新赋值为1(表示年满)。步骤2继续,直到日期合理为止。
Data& Data::operator+=(int day)
{
if (day < 0)//这里表示+=的天数是一个负数,复用-=操作符
{
*this -= -day;
}
else
{
_day += day;
while (_day > GetMonthDay(_year, _month))//不合理的日期继续执行
{
_day -= GetMonthDay(_year, _month);
_month++;
if (_month > 12)
{
_year++;
_month = 1;
}
}
}
return *this;//this不会因为函数结束而销毁,可以用引用做返回值。
}
日期 + 天数
实现+,我们可以直接复用+=,但是需要注意,这个日期本身不会改变,例如:ret=i+1,i本身的值不会变。
Data Data::operator+(int day)const//this不会改变,用const修饰
{
Data ret(*this);//利用this拷贝构造需要返回改变的ret
ret += day;
return ret;//ret出了函数作用域销毁,不可引用做返回值
}
日期 -= 天数
实现思路:1.日期对象的天数减上该天数 2.判断日期是否合理,若不合理,月份month--,day+=此年此月的天数,若month<1(表示该年已完) ,month=12,year--。继续执行步骤2,直到日期合理为止。
Data& Data::operator-=(int day)
{
if (day < 0)//表示减一个负数,相当于+这个数的正数
{
*this += -day;//复用+=
}
else
{
_day -= day;//步骤1
while (_day <= 0)//步骤2
{
_month--;
if (_month < 1)
{
_year--;
_month = 12;
}
_day += GetMonthDay(_year, _month);
}
}
return *this;
}
日期 - 天数
与+一样,我们复用-=,同样需要注意的问题和+的重载一样
Data Data::operator-(int day)const
{
Data ret(*this);
ret -= day;
return ret;
}
前置 ++
一样可以复用+=,对象日期+1
Data& Data::operator++()
{
*this += 1;
return *this;//出了函数作用域,this不会销毁,引用做返回值
}
后置 ++
由于前置++和后置++的运算符均为++,为了区分它们的运算符重载,我们给后置++的运算符重载的参数加上一个int型参数,无需传实参,只是为了构成重载。
Data Data::operator++(int)
{
Data ret(*this);
*this += 1;
return ret;
}后置++也是需要返回加了之前的值,只能先用对象ret保存之前的值,然后对象日期加一,最后返回ret对象,ret出了函数作用域,销毁,不能引用做返回值。
前置 --
可以复用-=,其他需要注意的和++一样
Data& Data::operator--()
{
*this -= 1;
return* this;
}
后置 --
Data Data::operator--(int)
{
Data ret(*this);
*this -= 1;
return ret;
}
日期类的大小关系比较
日期类比较有六个(> < == != >= <=),但是我们只需要实现两个,其他复用便可。
注:日期比较大小,说明本身都不会改变,都需要用cosnt修饰。
>运算符的重载
bool Data::operator>(const Data& d)const
{
return _year > d._year || _month > d._month || _day > d._day;
}
==运算符的重载
bool Data::operator==(const Data& d)const
{
return _year == d._year && _month == d._month && _day == d._day;
}
<运算符的重载
bool Data::operator<(const Data& d)const
{
return !(*this > d || *this == d);
}
>=运算符的重载
bool Data::operator>=(const Data& d)const
{
return !(*this < d);
}
<=运算符的重载
bool Data::operator<=(const Data& d)const
{
return !(*this > d);
}
!=运算符的重载
bool Data::operator!=(const Data& d)const
{
return !(*this == d);
}
日期 - 日期
返回的是两个日期间隔的天数。
实现思路:让小的那个日期不断加1,也用一个count记录一下小的加1的次数,直到与大的那个相等,结束,此时count就是两个日期间隔天数。
若是第一个日期大于第二个日期,则返回这个差值的正值,若第一个日期小于第二个日期,则返回这个差值的负值。
int Data::operator-(const Data& d)const
{
Data max = *this;
Data min = d;
int flag = 1;
int count = 0;
if (max < min)
{
max = d;
min = *this;
flag = -1;
}
while (max != min)
{
count++;
min++;
}
return count*flag;
}
今天星期几
1900,1,1是参考日期星期一,用需要判断星期几的日期-这个参考日期得到间隔天数,一周是7天,用得到的间隔天数%7(取值在0-6之间),就能得到星期几。
void Data::IsWeekDay()const
{
int day=*this - Data(1990,1,1);//匿名对象生命周期就在这一行
const char* days[7] = {"星期一","星期二", "星期三", "星期四", "星期五", "星期六", "星期天" };
cout << days[day % 7] << endl;
}