一、头文件的声明(Date.h)
日期类的实现,将按以下声明依次进行,其中因为Print函数比较短,直接放到类里面让其变成内联函数
头文件:
#pragma once
#include<iostream>
using namespace std;
class Date
{
public:
// 获取某年某月的天数
int GetMonthDay(int year, int month);
void Print() const
{
cout << _year << "年" << _month << "月" << _day<<"日" << endl;
}
// 全缺省的构造函数
Date(int year = 2022, int month = 5, int day = 9);
// 拷贝构造
Date(const Date& d);
// >运算符重载
bool operator>(const Date& d) const;
bool operator==(const Date& d) const;
bool operator >= (const Date& d) const;
bool operator < (const Date& d) const;
bool operator <= (const Date& d) const;
bool operator != (const Date& d) const;
//日期类连续赋值
Date& operator=(const 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;
// 日期-日期 返回天数
int operator-(const Date& d) const;
// 前置--
Date& operator--();
// 后置--
Date operator--(int) ;
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& in, Date& d);
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& out, const Date& d);
istream& operator>>(istream& in, Date& d);
1、✨获取天数的函数
而我们实现日期类经常要用到某月有多少天,在这里先把获得某月有多少天的函数实现出来。实现时先检查传参有没有问题,在注意把数组设置成静态的,出了作用域还能访问,其次我们先判断这个月是不是二月份,避免判断某年是平年还是闰年一大堆操作后,发现月份不是二月份
获取天数函数:
int Date::GetMonthDay(int year, int month)
{
if (month > 13 || month <= 0 )
{
cout << "日期非法" << endl;
return 0;
}
static int DayArr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
if (month != 2)
{
return DayArr[month];
}
else
{
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
return 29;
else
return 28;
}
}
2、✨日期类的拷贝构造函数
(1)全缺省拷贝构造构造
全缺省拷贝构造构造:
Date::Date(int year , int month , int day )
{
if (month > 13 || month <= 0 || day > GetMonthDay(year, month) || day <= 0)
{
cout << "日期非法" << endl;
}
_year = year; _month = month; _day = day;
(2)用一个类初始化另外一个类
用一个类初始化另外一个类:
Date::Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
二、日期类的大小比较(Date.cpp)
由于日期类的大小比较,均不涉及对自身的改变,对此,我们统一用const来修饰this指针,让其变成const成员函数,减少代码的出错性
1、✨ > > >运算符重载
在这里我们找出所有日期a大于日期b的情况,第一种:年比年大。第二种:年相同,月比月大。第三种:年和月都相同,日比日大。在依次向下写就完成了>(大于)的比较
>运算符重载:
bool Date::operator>(const Date& d) const
{
if (this->_year > d._year)
return true;
else if (this->_year == d._year && this->_month > d._month)
return true;
else if (this->_year == d._year && this->_month == d._month && this->_day > d._day)
return true;
else
return false;
}
2、✨ = = == ==运算符重载
==运算符重载:
bool Date::operator==(const Date& d) const
{
return this->_year == d._year
&& this->_month == d._month
&& this->_day == d._day;
}
3、✨ > = 、 < 、 < = 、 ! = >=、<、<=、!= >=、<、<=、!=对 > 、 = = >、== >、==复用
>=、<、<=、!=复用:
bool Date::operator >= (const Date& d) const
{
return *this > d || *this == d;
}
bool Date::operator<(const Date& d) const
{
return !(*this >= d);
}
bool Date::operator <= (const Date& d) const
{
return !(*this > d);
}
bool Date::operator != (const Date& d) const
{
return !(*this == d);
}
三、日期类的计算(Date.cpp)
1、✨日期类的连续赋值
在内置类型的适合我们经常有连续赋值的习惯,类似 a 1 = a 2 = a 3 a1=a2=a3 a1=a2=a3 这种,而日期类也支持连续赋值的操作。对此我们返回值不能写void,而应该返回对象,而返回引用,我们可以减少拷贝,从而提高效率
日期类连续赋值:
Date& Date::operator=(const Date& d)
{
this->_year = d._year;
this->_month = d._month;
this->_day = d._day;
return *this;
}
2、✨日期类的加法
(1) + = += +=运算符重载和 + + +对 + = += +=的复用
日期类的+=改变了自身,不能加const修饰this 在这里我们也返回引用提高效率,而日期的+返回的是加之前的值,不能返回引用,但是可以加const修饰this 月份会因日相加而改变,这时我们得考虑月份变成13的情况。而如果+的天数是负数,那么我们可以调用-=运算符重载函数来实现它, − = -= −=运算符重载我们在下面实现
+ = += +=运算符重载和 + + +对 + = += +=的复用:
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) const
{
Date tmp(*this);
tmp += day;
return tmp;
}
(2)前置 + + ++ ++和后置 + + ++ ++重载
稍微注意:后置++比前置++多一个参数(int),同时后置返回的临时变量,不能添加引用,同时两个this都被改变了,不加const修饰
前置++和后置++重载:
Date& Date::operator++()
{
*this += 1;
return *this;
}
Date Date::operator++(int)
{
Date temp(*this);
*this += 1;
return temp;
}
3、✨日期类减法
(1) − = -= −=运算符重载和 − - −对 − = -= −=的复用
− = -= −=运算符实现和上面 + = += +=类似,且可以相互复用(当参数day<0),这里注意我们是要借上个月份的天数来减,因此必须先 − − m o n t h --month −−month,再加上上个月天数。而不是像 + = += +=运算符重载实现那样先减去这个月天数再 + + m o n t h ++month ++month
− = -= −=运算符重载和 − - −对 − = -= −=的复用:
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) const
{
Date temp(*this);
temp -= day;
return temp;
}
(2)前置 − − -- −−和后置 − − -- −−重载
前置 − − -- −−和后置 − − -- −−重载:
Date& Date::operator--()
{
*this -= 1;
return *this;
}
Date Date::operator--(int)
{
Date temp(*this);
*this -= 1;
return temp;
}
(3)日期 − - −日期重载
日期类相减不需要日期本身,因此用const修饰。由于采用运算法求日期减去日期比较麻烦,还好考虑差有几年,几月,甚至几月中是否包括二月,所以在这样我们采用小日期自增的方式实现(也可以是大日期自减),用一个变量n记录再返回就行了
)日期 − - −日期重载:
int Date::operator-(const Date& d)const
{
Date max = *this;
Date min = d;
int flag = 1;
if (*this < d)
{
max = d;
min = *this;
flag = -1;
}
int n = 0;
while (min != max)
{
++min;
++n;
}
return n*flag;
}
总结:
欢迎阅读小白的文章,如有错误,请严厉指出。下一篇博客我们将进入类和对象下,期待我们下一篇博客见面!!!