目录
一.6个默认成员函数
二.基本功能函数
三.日期与天数的加减
四.前后置++和--
五.比较运算符重载
六.日期减日期
七.全部代码
1.Date.h
2.Date.cpp
C++初学者都可以在学习完类和对象后写一个日期类,以下是实现细节。
对于日期类默认成员函数使用编译器生成的足矣,这里就不多赘述。
提醒一下对于赋值运算符重载需要判断是不是自己给自己赋值。
对于我们实现日期+-天数有用的基本功能函数。
1.GetMonthDay(返回对应月份的天数,也考虑了闰年二月天数变化)
// 获取某年某月的天数
int Date::GetMonthDay(int year, int month)
{
static int arr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//数组扩大1下标就不用-1了
if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))//判断闰年
return arr[month] + 1;
return arr[month];
}
2.Judge(判断月份是否合法)
//判断日期是否合法
bool Date::judge()
{
if (_month <= 12 && _month > 0 && _day <= GetMonthDay(_year, _month) && (_day > 0))//判断月份和天数是不是正常的
return true;
return false;
}
3.Print(输出日期)
//输出日期
void Date::Print()
{
cout << _year << " " << _month << " " << _day << endl;
}
我们可以实现+=和-=的功能,然后+和-分别复用+=和-=的功能。
1.+=和+
// 日期+=天数
Date& Date::operator+=(int day)//可以理解为让日期一个月一个月往前走
{
_day += day;//直接把天数加上去
while (!judge())//一直对日期进行处理,直到合法为止
{
_day -= GetMonthDay(_year, _month);//这里注意_day是先减_month是后++的
_month++;
if (_month == 13)//月份越界就让年份加1,相当于月份变为下一年的1月
{
_year++;
_month = 1;
}
}
return *this;//引用返回就直接返回*this
}
// 日期+天数
Date Date::operator+(int day)
{
Date tmp(*this);//创建临时对象
tmp += day;//复用+=
return tmp;//不是引用返回所以是返回临时对象
}
2.-=和-
// 日期-=天数
Date& Date::operator-=(int day)//可以理解让日期一个月一个月往后退
{
_day -= day;//和+=一样直接让_day减day
while (!judge())//一直对日期处理直到合法为止
{
_month--;
if (_month == 0)//月份非法就让year-1,相当于是到了去年的12月
{
_year--;
_month = 12;
}
_day += GetMonthDay(_year, _month);//注意这里是月份先减1,然后才加天数,和+=是相反的
}
return *this;//引用返回所以是返回*this
}
// 日期-天数
Date Date::operator-(int day)
{
Date tmp(*this);//创建临时对象
tmp -= day;//复用-=
return tmp;//不是引用返回所以是返回临时对象
}
++和--复用+=和-=就可以,需要注意的是前置和后置在函数原型上的区别。
1.++
// 前置++
Date& Date::operator++()
{
*this += 1;//复用+=
return *this;//注意是引用返回
}
// 后置++
Date Date::operator++(int)//后置++需要在参数表加一个int用来占位,用来区分前后置++,编译器会进行特殊处理
{
++(*this);//自身也要++
Date tmp(*this);//创建临时对象
return tmp;//注意事项传值返回
}
2.--
// 前置--
Date& Date::operator--()
{
*this -= 1;//复用-=
return *this;//注意是引用返回
}
// 后置--
Date Date::operator--(int)//后置--需要在参数表加一个int用来占位,用来区分前后置--,编译器会进行特殊处理
{
--(*this);//自身也要--
Date tmp(*this);//创建临时对象
return tmp;//注意事项传值返回
}
只需要实现==和>或<,其他的比较运算符复用前两个就行。
// >运算符重载
bool Date::operator>(const 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==(const Date& d)
{
if (_year == d._year && _month == d._month && _day == d._day)//全部都一样就返回true
return true;
return false;
}
// >=运算符重载
bool Date::operator >= (const Date& d)
{
return *this > d || *this == d;//>=就是>或者==
}
// <运算符重载
bool Date::operator < (const Date& d)
{
return !(*this > d || *this == d);//<就是>=的取反
}
// <=运算符重载
bool Date::operator <= (const Date& d)
{
return !(*this > d);//<=就是>的取反
}
// !=运算符重载
bool Date::operator != (const Date& d)
{
return !(*this == d);//!=就是==的取反
}
日期-日期的实现方式有很多,我们这里直接用暴力,就是用小日期一直++天数,直到等于大的日期为止(优化版本就是按月来算)。另一种方式是让两个日期都对一个小的日期计算天数,然后再相减(不用判断谁大谁小)。
// 日期-日期 返回天数
int Date::operator-(const Date& d)
{
Date tmp, target;//用两个临时变量计算
int day = 0, flag = 0;//day是计算天数,flag是判断*this是否小于d
if (*this < d)
{
flag = 1;//*this小于d,令flag=1
tmp = (*this);//tmp默认是小的日期
target = (d);//target默认是大的日期
}
else
{
tmp = (d);//tmp默认是小的日期
target = (*this);//target默认是大的日期
}
while (tmp != target)//两个日期不相等就一直处理
{
tmp++;//小日期++
day++;//计算天数差值
}
if (flag)//如果*this小于d,那么天数差值就是负数
day *= -1;
return day;
}
#pragma once
class Date
{
public:
// 获取某年某月的天数
int GetMonthDay(int year, int month);
//判断日期是否合法
bool judge();
//输出日期
void Print();
// 全缺省的构造函数
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// 拷贝构造函数
// d2(d1)
Date(const Date& d);
// 赋值运算符重载
// d2 = d3 -> d2.operator=(&d2, d3)
Date& operator=(const Date& d);
// 析构函数
~Date();
// 日期+=天数
Date& operator+=(int day);
// 日期+天数
Date operator+(int day);
// 日期-天数
Date operator-(int day);
// 日期-=天数
Date& operator-=(int day);
// 前置++
Date& operator++();
// 后置++
Date operator++(int);
// 后置--
Date operator--(int);
// 前置--
Date& operator--();
// >运算符重载
bool operator>(const Date& d);
// ==运算符重载
bool operator==(const Date& d);
// >=运算符重载
bool operator >= (const Date& d);
// <运算符重载
bool operator < (const Date& d);
// <=运算符重载
bool operator <= (const Date& d);
// !=运算符重载
bool operator != (const Date& d);
// 日期-日期 返回天数
int operator-(const Date& d);
private:
int _year;
int _month;
int _day;
};
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include"Date.h"
using namespace std;
// 获取某年某月的天数
int Date::GetMonthDay(int year, int month)
{
static int arr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//数组扩大1下标就不用-1了
if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))//判断闰年
return arr[month] + 1;
return arr[month];
}
//判断日期是否合法
bool Date::judge()
{
if (_month <= 12 && _month > 0 && _day <= GetMonthDay(_year, _month) && (_day > 0))//判断月份和天数是不是正常的
return true;
return false;
}
//输出日期
void Date::Print()
{
cout << _year << " " << _month << " " << _day << endl;
}
// 拷贝构造函数
// d2(d1)
Date::Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
// 赋值运算符重载
// d2 = d3 -> d2.operator=(&d2, d3)
Date& Date::operator=(const Date& d)
{
if (&d != this)
{
_year = d._year;
_month = d._month;
_day = d._day;
return *this;
}
}
// 析构函数
Date::~Date()
{
_year = 0;
_month = 0;
_day = 0;
}
// 日期+=天数
Date& Date::operator+=(int day)//可以理解为让日期一个月一个月往前走
{
_day += day;//直接把天数加上去
while (!judge())//一直对日期进行处理,直到合法为止
{
_day -= GetMonthDay(_year, _month);//这里注意_day是先减_month是后++的
_month++;
if (_month == 13)//月份越界就让年份加1,相当于月份变为下一年的1月
{
_year++;
_month = 1;
}
}
return *this;//引用返回就直接返回*this
}
// 日期+天数
Date Date::operator+(int day)
{
Date tmp(*this);//创建临时对象
tmp += day;//复用+=
return tmp;//不是引用返回所以是返回临时对象
}
// 日期-天数
Date Date::operator-(int day)
{
Date tmp(*this);//创建临时对象
tmp -= day;//复用-=
return tmp;//不是引用返回所以是返回临时对象
}
// 日期-=天数
Date& Date::operator-=(int day)//可以理解让日期一个月一个月往后退
{
_day -= day;//和+=一样直接让_day减day
while (!judge())//一直对日期处理直到合法为止
{
_month--;
if (_month == 0)//月份非法就让year-1,相当于是到了去年的12月
{
_year--;
_month = 12;
}
_day += GetMonthDay(_year, _month);//注意这里是月份先减1,然后才加天数,和+=是相反的
}
return *this;//引用返回所以是返回*this
}
// 前置++
Date& Date::operator++()
{
*this += 1;//复用+=
return *this;//注意是引用返回
}
// 后置++
Date Date::operator++(int)//后置++需要在参数表加一个int用来占位,用来区分前后置++,编译器会进行特殊处理
{
++(*this);//自身也要++
Date tmp(*this);//创建临时对象
return tmp;//注意事项传值返回
}
// 后置--
Date Date::operator--(int)//后置--需要在参数表加一个int用来占位,用来区分前后置--,编译器会进行特殊处理
{
--(*this);//自身也要--
Date tmp(*this);//创建临时对象
return tmp;//注意事项传值返回
}
// 前置--
Date& Date::operator--()
{
*this -= 1;//复用-=
return *this;//注意是引用返回
}
// >运算符重载
bool Date::operator>(const 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==(const Date& d)
{
if (_year == d._year && _month == d._month && _day == d._day)//全部都一样就返回true
return true;
return false;
}
// >=运算符重载
bool Date::operator >= (const Date& d)
{
return *this > d || *this == d;//>=就是>或者==
}
// <运算符重载
bool Date::operator < (const Date& d)
{
return !(*this > d || *this == d);//<就是>=的取反
}
// <=运算符重载
bool Date::operator <= (const Date& d)
{
return !(*this > d);//<=就是>的取反
}
// !=运算符重载
bool Date::operator != (const Date& d)
{
return !(*this == d);//!=就是==的取反
}
// 日期-日期 返回天数
int Date::operator-(const Date& d)
{
Date tmp, target;//用两个临时变量计算
int day = 0, flag = 0;//day是计算天数,flag是判断*this是否小于d
if (*this < d)
{
flag = 1;//*this小于d,令flag=1
tmp = (*this);//tmp默认是小的日期
target = (d);//target默认是大的日期
}
else
{
tmp = (d);//tmp默认是小的日期
target = (*this);//target默认是大的日期
}
while (tmp != target)//两个日期不相等就一直处理
{
tmp++;//小日期++
day++;//计算天数差值
}
if (flag)//如果*this小于d,那么天数差值就是负数
day *= -1;
return day;
}