目录
第一节:日期类介绍
这次我们将写一个属于自己的日期类,它能够对日期进行一些操作,比如日期-日期得到日期的时间间隔,日期-天数,日期+天数等......下面我们来一一实现。
第二节:日期类实现
2-1.构造函数和成员变量
namespace LUC
{
class Date
{
public:
// 全缺省构造
Date(int year = 1900, int month = 1, int day = 1):
_year(year),
_month(month),
_day(day)
{}
// 拷贝构造
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
private: // 保存日期的成员变量
int _year;
int _month;
int _day;
};
};
2-2.析构函数
因为日期类的成员变量都是内置类型,所以不需要显示的写出析构函数。
2-3.赋值重载运算符
// 赋值重载运算符
Date& operator=(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
return *this;
}
2-4.得到某个月的天数
这个函数是为了在对日期进行加减操作时得到正确的年、月、日,我们不会直接调用它,而是在进行加减操作时间接调用它,所以可以把它设置成private函数。
// 得到某年某月的天数
int GetMonthDays(int year,int month)
{
int monthsDays[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
if (month == 2 && (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))) // 判断是不是闰月
return 29;
return monthsDays[month];
}
2-5.日期+=天数
得到当前日期之后x天的日期:
// 日期+=天数
Date& operator+=(int days)
{
int Days = days + _day; // 得到总的天数
while (Days > GetMonthDays(_year, _month)) // 只要月份需要进1就一直循环
{
Days -= GetMonthDays(_year, _month); // 减去当月天数
_month+=1; // 月份进1
if (_month > 12) // 年份进1
{
_year += 1;
_month = 1;
}
}
_day = Days;
return *this;
}
2-6.日期+天数
日期+天数得到一个临时类存储结果,调用的类不修改:
// 日期+天数
Date operator+(int days)
{
Date tmp(*this); // 创建一个临时类
tmp += days; // 复用日期+=天数
return tmp;
}
2-7.日期-=天数
我们可以把每个月的天数和_day相加,直到它大于days为止:
// 日期-=天数
Date operator-=(int days)
{
int Day = _day;
while (days >= Day)
{
_month -= 1;
if (_month < 1)
{
_year--;
_month = 12;
}
Day += GetMonthDays(_year, _month);
}
_day = Day - days;
return *this;
}
2-8.日期-天数
它也可以复用日期-=天数:
// 日期-天数
Date operator-(int days)
{
Date tmp(*this);
tmp -= days;
return tmp;
}
2-9.前置++
前置++就是先加1天再使用,所以可以直接复用+=:
// 前置++
Date& operator++()
{
return *this += 1;
}
2-10.后置++
后置++是先使用后加1天:
它会报错,这是因为前置++和它不能构成重载(参数相同),可以设置一个参数,但是我们并不使用它:
// 后置++
Date operator++(int)
{
Date tmp(*this);
*this += 1;
return tmp;
}
2-11.前置--
// 前置--
Date& operator--()
{
return *this -= 1;
}
2-12.后置--
// 后置--
Date operator--(int)
{
Date tmp(*this);
*this -= 1;
return tmp;
}
2-13.各种运算符重载
// ==重载
bool operator==(const Date& d)
{
if (_year == d._year && _month == d._month && _day == d._day)
return true;
return false;
}
// >重载
bool operator > (const Date& d)
{
if (_year > d._year)
return true;
else if (_year == d._year)
{
if (_month > d._month)
return true;
else if (_month == d._month)
{
if (_day > d._day)
return true;
}
}
return false;
}
// < 重载 可复用==和>
bool operator < (const Date& d)
{
return !(*this == d || *this > d);
}
// >= 重载 可复用==和>
bool operator >=(const Date& d)
{
return *this == d || *this > d;
}
// <= 重载 可复用>
bool operator <=(const Date& d)
{
return !(*this > d);
}
2-14.日期-日期
日期-日期得到间隔的天数,首先我们需要写一个函数得到某一年的天数:
// 得到某年的天数
int GetYearDays(int year)
{
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))// 判断闰年
{
return 356;
}
return 355;
}
然后才能写日期-日期的功能函数:
// 日期-日期
int operator-(const Date& d)
{
int days = _day;
int year = _year;
int month = _month;
while (year > d._year)
{
year--;
days += GetYearDays(year);
}
while (month > d._month)
{
month--;
days += GetMonthDays(year, month);
}
while (month < d._month)
{
days -= GetMonthDays(year,month);
month++;
}
return days - d._day;
}
2-15.流插入重载
流插入重载用来向文件插入数据:
// <<重载
std::iostream& operator<<(std::iostream& stream)
{
stream << _year << "-" << _month << "-" << _day;
return stream;
}
但是当我们调用时会报错:
这是因为对于两个操作数的运算符来说,左操作数会作为第一个参数,右边会作为第二个参数,而第一个参数是this指针,所以会造成参数类型匹配。
解决办法,使用友元函数,友元函数不属于这个类,但是可以直接访问类的私有成员,它在类中声明,在类外定义:
// <<重载
friend std::ostream& operator<<(std::ostream& stream, const Date& d);
std::ostream& operator<<(std::ostream& stream, const Date& d)
{
stream << d._year << "-" << d._month << "-" << d._day;
return stream;
}
2-16.流提取重载
流提取同理,也要使用友元函数:
// >>重载
friend std::istream& operator>>(std::istream& stream, Date& d);
std::istream& operator>>(std::istream& stream,Date& d)
{
stream >> d._year >> d._month >> d._day;
return stream;
}
第三节:完整代码
至此,完整代码如下,可以自己做一下测试:
#include <iostream>
namespace LUC
{
class Date
{
private:
// 得到某年某月的天数
int GetMonthDays(int year,int month)
{
int monthsDays[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
if (month == 2 && (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))) // 判断是不是闰月
return 29;
return monthsDays[month];
}
// 得到某年的天数
int GetYearDays(int year)
{
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))// 判断闰年
{
return 366;
}
return 365;
}
public:
// 全缺省构造
Date(int year = 1900, int month = 1, int day = 1):
_year(year),
_month(month),
_day(day)
{}
// 拷贝构造
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
// 赋值重载运算符
Date& operator=(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
return *this;
}
// 日期+=天数
Date& operator+=(int days)
{
int Days = days + _day; // 得到总的天数
while (Days > GetMonthDays(_year, _month)) // 只要月份需要进1就一直循环
{
Days -= GetMonthDays(_year, _month); // 减去当月天数
_month+=1; // 月份进1
if (_month > 12) // 年份进1
{
_year += 1;
_month = 1;
}
}
_day = Days;
return *this;
}
// 日期+天数
Date operator+(int days)
{
Date tmp(*this); // 创建一个临时类
tmp += days; // 复用日期+=天数
return tmp;
}
// 日期-=天数
Date& operator-=(int days)
{
int Day = _day;
while (days >= Day)
{
_month -= 1;
if (_month < 1)
{
_year--;
_month = 12;
}
Day += GetMonthDays(_year, _month);
}
_day = Day - days;
return *this;
}
// 日期-天数
Date operator-(int days)
{
Date tmp(*this);
tmp -= days;
return tmp;
}
// 前置++
Date& operator++()
{
return *this += 1;
}
// 后置++
Date operator++(int)
{
Date tmp(*this);
*this += 1;
return tmp;
}
// 前置--
Date& operator--()
{
return *this -= 1;
}
// 后置--
Date operator--(int)
{
Date tmp(*this);
*this -= 1;
return tmp;
}
// ==重载
bool operator==(const Date& d)
{
if (_year == d._year && _month == d._month && _day == d._day)
return true;
return false;
}
// >重载
bool operator > (const Date& d)
{
if (_year > d._year)
return true;
else if (_year == d._year)
{
if (_month > d._month)
return true;
else if (_month == d._month)
{
if (_day > d._day)
return true;
}
}
return false;
}
// < 重载 可复用==和>
bool operator < (const Date& d)
{
return !(*this == d || *this > d);
}
// >= 重载 可复用==和>
bool operator >=(const Date& d)
{
return *this == d || *this > d;
}
// <= 重载 可复用>
bool operator <=(const Date& d)
{
return !(*this > d);
}
// 日期-日期
int operator-(const Date& d)
{
int days = _day;
int year = _year;
int month = _month;
while (year > d._year)
{
year--;
days += GetYearDays(year);
}
while (month > d._month)
{
month--;
days += GetMonthDays(year, month);
}
while (month < d._month)
{
days -= GetMonthDays(year,month);
month++;
}
return days - d._day;
}
// <<重载
friend std::ostream& operator<<(std::ostream& stream, const Date& d);
// >>重载
friend std::istream& operator>>(std::istream& stream, Date& d);
private: // 保存日期的成员变量
int _year;
int _month;
int _day;
};
// 友元函数的实现
std::ostream& operator<<(std::ostream& stream, const Date& d)
{
stream << d._year << "-" << d._month << "-" << d._day;
return stream;
}
std::istream& operator>>(std::istream& stream,Date& d)
{
stream >> d._year >> d._month >> d._day;
return stream;
}
};
下期预告:
下次补充类和对象的内容:
1、友元函数与友元类
2、 匿名对象
3、编译器优化
4、new开辟栈空间