在生活当中,关于日期我们肯定不陌生,比如各种节日都要用一个日期来定义是在哪一天;而对于日期来说我们不妨把它归为一类,在现实生活中日期是一个实体,我们把日期构建为日期类,下面我们就来实现关于日期类经常用的相关操作。
我们知道描述一个日期是以哪一年、哪一月、哪一天来描述的,所以在我们自定义类型构建日期类的时候,日期类的成员就是年、月和日,日期类的成员函数就是来实现关于日期类的各种操作的,构建如下:
#include
using namespace std;
//日期类
class Date
{
public:
void Print();
int GetMonthDay(int year, int month);
Date(int year=0,int month=0,int day=0); //构造函数
Date(const Date& d); //拷贝构造函数
//运算符重载,判断两个日期类的大小关系
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 n);
Date operator+(int n) const;
Date& operator-=(int n);
Date operator-(int n);
//实现两个日期相差的天数
int operator-(const Date& d);
//实现日期的自增和自减
Date& operator++();
Date operator++(int);
Date& operator--();
Date operator--(int);
private:
int _year;
int _month;
int _day;
};
对于日期来说,获取每个月的天数是有很大意义的,因为不同的年份和月份造成的结果有特殊性,比如每一年的二月份,要判断是否为润年还是平年,如果是平年就28天,润年就是29天。还有为了实现其它日期的操作也是需要这个函数的,获取每个月天数的函数如下:
//在日期类当中的获取每个月天数的函数
int Date::GetMonthDay(int year, int month)
{
static int sum[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
int day = sum[month];
//判断是否为润年并且为2月份
if ((month == 2) &&
((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))
{
day++;
}
return day;
}
我们知道当我们创建一个日期类的过程中,编译器会帮我们调用构造函数,如果我们不实现构造函数,那么编译器会帮我们自动生成一个,但是自动生成的默认构造函数是不对内置类型进行处理的,从而也初始化不了对象;所以我们必须要自己写一个构造函数,并且这个构造函数还要判断日期是否合理,比如2022.15.52 这个日期就是不合理的。构造函数如下:
//打印日期函数
void Date::Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
Date::Date(int year, int month, int day)
{
//先进行初始化
_year = year;
_month = month;
_day = day;
//再判断日期是否合理
if((year<1) || (month>12&&month<1)
|| (day > GetMonthDay(year, month)))
{
cout << "日期不合法:" ;
Print();
}
}
在以前的C语言语法中我们只能对内置类型进行运算符操作,不能对自定义类型(如结构体)进行运算符操作;C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数;所以我们就可以对自定义类型进行运算符操作,从而可以实现两个日期的大小关系,实现函数如下:
//判断日期d1是否打印日期d2
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;
}
else
{
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 (*this > d) || (*this == d);
}
bool Date::operator<(Date& d)
{
return !(*this >= d);
}
bool Date::operator<=(Date& d)
{
return (*this < d) || (*this == d);
}
bool Date::operator!=(Date& d)
{
return !(*this == d);
}
关于日期类的对象我们还有很多要实现的,比如在日常生活中我们想知道一个日期加减某一天是多少,而在日期类中我们要可以实现出来,下面对+= 、+和-、-=运算符的实现,要注意的是+=才能对本身进行改变,而+并不能对本身改变;函数如下:
//日期加上天数后是多少
Date& Date::operator+=(int n)
{
//如果天数为负值就对-=运算符复用
if (n < 0)
{
return *this -= n;
}
_day += n;
while (_day > GetMonthDay(_year, _month))
{
_day -= GetMonthDay(_year, _month);
_month++;
if (_month == 13)
{
_month = 1;
_year++;
}
}
return *this;
}
Date Date::operator+(int n) const
{
Date ret = *this;
ret += n;
return ret;
}
Date& Date::operator-=(int n)
{
if (n < 0)
{
return *this += -n;
}
_day -= n;
while (_day <= 0)
{
_month--;
if (_month == 0)
{
_month = 12;
_year--;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
Date Date::operator-(int n)
{
Date ret = *this;
ret -= n;
return ret;
}
在日常生活中日期加上日期是没有意义的,但日期减去一个日期就是两个日期之间的天数了,是有很大意义的,我们也可以在类中来实现,函数如下:
//日期-日期,参数是Date类型,和上面的日期减天数函数构成重载
int Date::operator-(const Date& d)
{
int count = 0;
int flag = 1;
Date Max = *this;
Date Min(d);
if (Min>Max)
{
Max = d;
Min = *this;
flag = -1;
}
while (Min != Max)
{
Min += 1;
count++;
}
return count * flag;
}
在运算符中自增和自减是经常用到的,我们也可以来实现自定义类型日期类的自增和自减,但是要分为前置++还是后置++;前置++改变了先自增然后才使用,改变了自己本身;而后置++是先使用然后再自增;我们要注意其中的差别才行。
//前置++,对+=运算符进行复用
Date& Date::operator++()
{
*this += 1;
return *this;
}
//后置++,没使用之前本身没有改变
Date Date::operator++(int)
{
Date ret = *this;
*this += 1;
return ret;
}
//前置--
Date& Date::operator--()
{
*this -= 1;
return *this;
}
//后置--
Date Date::operator--(int)
{
Date ret = *this;
*this -= 1;
return ret;
}