【C++】日期类实现
日期类实现
1、关系运算符重载
>、>=、<、<=、==、!=
如果判断a是否大于b,可以先写判断a小于b和a等于b的函数,其他的复用
主要框架(.h文件)
#pragmaonce#include<assert.h>#include<iostream>using namespace std;class Date{public:// 友元函数声明friend ostream&operator<<(ostream&out,constDate&d);friend istream&operator>>(istream&in,Date&d);intGetMonthDay(intyear,intmonth){assert(month>0&&month<13);staticintmonthDayArray[13]={-1,31,28,31,30,31,30,31,31,30,31,30,31};if(month==2&&((year%4==0&&year%100!=0)||(year%400==0)))return29;elsereturnmonthDayArray[month];}// 只要不改变调用对象的函数都建议加constvoidPrint()const;boolCheckDate();Date(intyear=1,intmonth=1,intday=1);Date&operator+=(intday);Date operator+(intday)const;Date&operator-=(intday);Date operator-(intday)const;// ++d1; -> d1.operatpr++();Date&operator++();//d1++; -> d1.operatpr++(1);Date operator++(int);// --d1;Date&operator--();//d1;Date operator--(int);bool operator==(constDate&d)const;bool operator!=(constDate&d)const;bool operator<(constDate&d)const;bool operator<=(constDate&d)const;bool operator>(constDate&d)const;bool operator>=(constDate&d)const;// 日期-日期 难intoperator-(constDate&d)const;/*ostream& operator<<(ostream& out) { out << _year << "年" << _month << "月" << _day << "日" << endl; return out; }*/Date*operator&(){returnthis;// return nullptr;}constDate*operator&()const{returnthis;// return nullptr;}private:int_year;int_month;int_day;};ostream&operator<<(ostream&out,constDate&d);istream&operator>>(istream&in,Date&d);1.重载<
bool Date::operator<(constDate&d)const{if(_year<d._year){returntrue;}elseif(_year==d._year){if(_month<d._month){returntrue;}elseif(_month==d._month){return_day<d._day;}}returnfalse;}2.重载==
bool Date::operator==(constDate&d)const{return_year==d._year&&_month==d._month&&_day==d._day;}3.重载<=
bool Date::operator<=(constDate&d)const{return*this<d||*this==d;}4.重载>
bool Date::operator>(constDate&d)const{return!(*this<=d);}5.重载>=
bool Date::operator>=(constDate&d)const{return!(*this<d);}6.重载!=
bool Date::operator!=(constDate&d)const{return!(*this==d);}2、赋值运算符重载
1.获取某个月的天数
重载+和+=时,涉及日期进位,当日期为这个月的最后一天时,再加一天月份要进一位
intGetMonthDay(intyear,intmonth){assert(month>0&&month<13);staticintmonthDayArray[13]={-1,31,28,31,30,31,30,31,31,30,31,30,31};if(month==2&&((year%4==0&&year%100!=0)||(year%400==0)))return29;elsereturnmonthDayArray[month];}- 设置一个数组存放每个月的天数,以月份为下标
- 把数组设置为静态,因为函数会被调用多次,设置成静态,第一次创建之后,一直到程序结束后还在,可以避免函数调用时重复的创建数组
- 当月份为2时要判断是否是闰年
2.重载+=
用于给出一个已知日期,计算过了若干天后的日期
Date&Date::operator+=(intday)//这里必须是+= d1+100是错误的 d1没改变{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;}3.重载+
+和+=的方法类似,可以利用+=实现重载+
Date Date::operator+(intday)const{Date tmp=*this;tmp+=day;returntmp;}4.重载-=
Date&Date::operator-=(intday){if(day<0){return*this+=-day;}_day-=day;while(_day<=0){--_month;if(_month==0){_month=12;_year--;}// 借上⼀个⽉的天数_day+=GetMonthDay(_year,_month);}return*this;//第二种写法//*this=*this-day;//return *this;//拷贝次数多}5.重载日期-天数
利用-=重载-
Date Date::operator-(intday)const{Date tmp=*this;tmp-=day;returntmp;}6.重载日期-日期
intDate::operator-(constDate&d)const{Date max=*this;//存放大日期Date min=d;//存放小日期intflag=1;if(*this<d){max=d;min=*this;flag=-1;}//初始化计数器intn=0;while(min!=max){++min;++n;}returnn*flag;}- flag为标记符号,默认*this日期≥d日期,结果为正
- 调用Date类重载的<运算符,判断当前日期(this)是否小于d,若成立,说明d是大日期,
*this是小日期,执行大括号内逻辑 - 把大日期d赋值给max,把小日期*this赋值给min,falg更新符号为-1,最终结果取负,退出if语句
- 初始化一个计数器,统计从min到max之间的天数差
- 最终返回值:
若*this≥d:结果为正,flag=1,返回n
若*this<d:结果为负,flag=-1,返回-n
3、重载++、–
1.重载前置++
Date&Date::operator++(){*this+=1;//先把自己加一天return*this;//加完之后的样子}- 返回++之后的值
2.重载后置++
Date Date::operator++(int){Datetmp(*this);//保存自己当前的样子*this+=1;//把自己加一天returntmp;//返回保存下来的自己}- 返回++之前的值
3.重载前置–
Date&Date::operator--(){*this-=1;return*this;}- 返回–之后的值
4.重载后置–
Date Date::operator--(int){Date tmp=*this;*this-=1;returntmp;}- 返回–之前的值
4、重载<<、>>
对于自定义类型,编译器不知道如何打印,所以通过<<打印日期类对象
cin是istream类实例化对象,cout是ostream类实例化对象
将<<重载成全局函数
ostream&operator<<(ostream&out,constDate&d){out<<d._year<<"年"<<d._month<<"⽉"<<d._day<<"⽇"<<endl;returnout;}注意:因为该运算符重载函数写在全局,默认函数内部无法访问日期类的私有成员变量,所以把该函数设置成友元函数
friend ostream&operator<<(ostream&out,constDate&d);将>>重载成全局函数
istream&operator>>(istream&in,Date&d){cout<<"请依次输入年⽉日:";in>>d._year>>d._month>>d._day;if(!d.CheckDate()){cout<<"⽇期非法"<<endl;}returnin;}注意:两个参数都不能加const修饰
friend istream&operator>>(istream&in,Date&d);