日期类
class Date
{
public:
//成员函数
private:
int _year;
int _month;
int _day;
};
日期类成员对象: 年、月、日
实现功能: 成员函数
即用四个默认成员函数就可以实现一个日期类。
1.构造函数
实现日期年月日的初始化,函数包括年月日的初始化,传参(判断初始化当年是否为闰年,即获得当年2月具体的天数)
//获取某年具体的某一天
inline int GetMonthDay(int year, int month) //写成内联函数,减少函数调用栈开销
{
static int MonthDayArray[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//static 静态,保证数组中的天数不变
if(month == 2
&& ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
{
return 29; //实现瑞年2月输出29天
}
else
{
return MonthDayArray[month];
}
}
Date(int year = 1900, int month = 1, int day = 1)
{
if(year >= 1900 //保证日期的合法性
&& (month > 0 && month <= 13)
&& day <= GetMonthDay(year, month))
{
_year = year;
_month = month;
_day = day;
}
else
{
cout << "非法日期!" << endl;
}
}
2.析构函数
日期类的构造中没用开辟新空间,也没有打开文件等操作。因此使用系统的默认析构函数就够用
不需要自定义实现。
3.拷贝构造函数
日期类的拷贝构造,只用拷贝对象中的内容,即编译器默认实现的浅拷贝(按字节序依次拷贝)。
需要注意拷贝日期的const修饰,和函数参数传引用等问题。
Date(const Date& d) //拷贝构造函数
{
_year = d._year;
_month = d._month;
_day = d._day;
}
Date d1(2019, 5, 12);
Date d2;
d2(d1);
4.赋值运算符重载
函数原型:返回值类型 operator操作符(参数列表)
在日期类中用来实现:日期加减天数、日期减日期、日期比较赋值等
运算符重载可以写在全局中,也可写在类里面,一般建议写在类里面。使他们转换为内联函数,减少函数调用栈开销。
1) 日期加天数:实现 += 就可利用此运算符重载实现 + ++ 等运算符重载
思路: 日期+天数,利用循环 用日期的天数加上给定天数、判断日期天数大于本月的应有天数,则给月份加1、月份等于12时,年份加1,月份置为1,直到天数为本月合理天数结束返回。
Date& operator+=(int day) //函数返回值带引用,表示返回值变量在出了函数作用域还在
{
if(day < 0)
{ //日期小于0 则等于-正天数
return *this -= -day;
}
_day += day; //先把天数加起来
while(_day > GetMonthDay(_year, _month)) //天数不合理
{
if(_month == 12)
{ //月到12 则年加1
++_year;
_month = 1;
}
++_month;
_day -= GetMonthDay(_year, _month); //天数减去这月正常的天数,再取判断
}
return *this;
}
2)日期减天数:实现 -= 就可利用此运算符重载实现 - -- 等运算符重载
思路:日期减天天数,日期的天减去天数,循环判断日期天数是否小于等于0,月份减一,如果月份等于0,年份减一,月份置为12月
日期天数加上本月的合理天数再去判断。
Date& operator-=(int day)
{
if(_day < 0)
{ //数天小于0
return *this += -day;
}
_day -= day;
while(_day <= 0) //天数小于等于0进入循环
{
--_month; //月份为1 年份减一
if(_month == 0)
{
--_year;
_month = 12;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
3)日期 - 日期: 返回两个日期相差的天数
思路:取两个日期变量,表示两个日期。 小日期++,直到等于大日期。用计数器days记录 并返回
int operator-(const Date& d)
{
Date minDate(*this);
Date maxDate(d);
int flag = 1;
if(minDate > maxDate)
{
maxDate = *this;
minDate = d;
flag = -1;
}
int days = 0;
while(minDate != maxDate)
{
minDate += 1;
++days;
}
return days * flag;
}
4) 日期间的比较: boo类型返回值
实现 < > 就可以根据运算符重载对 >取反就可实现 <= >= 等
bool operator<(const Date& d) const
{
if((_year < d._year) //只要有一个小于就小于
|| (_year == d._year && _month < d._month)
|| (_year == d._year && _month == d._month && _day < d._day))
{
return true;
}
else
{
return false;
}
}
日期类具体实现C++代码如下:
成员函数建议都在写在类里面,默认内联。
此处的复制运算符重载,为测试程序没有写进类里。
Date.h
#include <iostream>
using std::cout;
using std::endl;
#pragma once
class Date
{
public:
//构造函数: 初始化对象、函数名与类名相同、无返回值、对象实例化时系统自动调用
//1.系统默认构造函数(没什么实际作用,自动调用后,初始化的对象还是随机值)
/*Date()
{ //无参构造函数
_year = 1900;
_month = 1;
_day = 1;
}*/
//2.用户自定义构造函数,通常构造函数还需要能判断日期的有效性
//Date(int year = 1900, int month = 1, int day = 1)
//{ //与上面构造函数构成重载,全缺省参数
// //一般推荐这种写法
// _year = year;
// _month = month;
// _day = day;
//}
//可返回某年某月具体有多少天
inline int GetMonthDay(int year, int month)
{
static int MonthArray[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if ((month == 2)
&& ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
{ //瑞年的2月是29天
return 29;
}
return MonthArray[month];
}
Date(int year = 1900, int month = 1, int day = 1)
{
if (year >= 1900
&& month > 0 && month < 13
&& day > 0 && day <= GetMonthDay(year, month))
{
_year = year;
_month = month;
_day = day;
}
else
{
cout << "非法输入" << endl;
}
}
//析构函数: 完成清理:如 malloc -> free fopen -> fclose
//1.析构函数名实在类名前加上字符~
//2.无参数 无返回值
//3.一个类只有一个析构函数,若未显示定义,系统会自动生成默认的析构函数
//4.对象生命周期结束时,C++编译系统对自动调用析构函数。
~Date()
{ //每次对象结束时,编译系统都会自动调用析构函数
cout << "析构函数调用" << endl;
}
//拷贝构造函数:创建相同的类对象、对构造函数传引用类型的对象,一般常用const修饰
//1.拷贝构造函数时=是构造函数的一个重载形式
//2.他的参数只用一个且必须使用引用传参,如果使用传值形式,会引发无穷递归调用
//3.没有自定义时,系统自动生成默认的拷贝构造函数(默认按字节序完成拷贝)
// 值拷贝/或浅拷贝
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
//赋值运算符重载
//运算符重载:有特殊函数名的函数
//函数原型:返回值类型+operator操作符(参数列表)
//1.不能通过其他符号来创建新的操作符
//2.重载操作符必须有一个类类型或者枚举类型的操作数
//3.用于内置类型的操作符,其含义不能改变
//4.作为类成员函数重载时,其形参看起来少一个,操作符有一个默认的形参this
//5. .* :: sizeof ?: . 五个运算符不能重载
//运算符重载一般可以写成全局的,但需要成员变量为公有的
//所以一般还是写在类里面
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++(); //前置++
Date operator++(int); //后置++
Date& operator--(); //前置--
Date operator--(int); //后置--
Date operator+(int day) const;
Date operator-(int day) const;
Date& operator+=(int day);
Date& operator-=(int day);
int operator-(const Date& d);
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
Date.cpp
#include "Date.h"
bool Date::operator>(const Date& d) const
{
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 Date::operator>=(const Date& d) const
{
if (*this < d)
{
return false;
}
else
{
return true;
}
}
bool Date::operator<(const Date& d) const
{
if (_year < d._year
|| (_year == d._year && _month < d._month)
|| (_year == d._year && _month == d._month && _day < d._day))
{
return true;
}
else
{
return false;
}
}
bool Date::operator<=(const Date& d) const
{
if (*this > d)
{
return false;
}
else
{
return true;
}
}
bool Date::operator==(const Date& d) const
{
return _year == d._year && _month == d._month && _day == d._day;
}
bool Date::operator!=(const Date& d) const
{
return _year != d._year || _month != d._month || _day != d._day;
}
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++() //前置++
{
*this += 1;
return *this;
}
Date Date::operator++(int) //后置++
{
Date ret(*this); //拷贝构造
*this += 1;
return ret;
}
Date Date::operator+(int day) const
{
Date ret = *this;
ret += day;
return ret;
}
Date& Date::operator--() //前置--
{
*this -= 1;
return *this;
}
Date Date::operator--(int) //后置--
{
Date ret(*this);
ret -= 1;
return ret;
}
Date Date::operator-(int day) const
{
Date ret = *this;
ret -= day;
return ret;
}
Date& Date::operator-=(int day)
{
_day -= day;
while (_day <= 0)
{
if (_month == 1)
{
_year--;
_month = 12;
}
else
{
_month--;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
int Date::operator-(const Date& d) //两个日期相减
{
Date maxDate(*this);
Date minDate(d);
int flag = 1;
if (maxDate < minDate)
{
flag = -1;
maxDate = d;
minDate = *this;
}
int days = 0;
while (minDate != maxDate)
{
minDate += 1;
++days;
}
return days * flag;
}
main.cpp
#include "Date.h"
//写测试程序
int main()
{
Date d1(2019, 5, 13);
d1.Print();
Date d2;
d2.Print();
Date d3(d1);
d3.Print();
cout << d3 - d2 << endl;
d3 += 18;
d3.Print();
d3 -= 10;
d3.Print();
(d2 + 10000).Print();
return 0;
}