目录
1.日期类的定义:Date.h
#pragma once
#include <iostream>
#include <assert.h>
using std::cout;
using std::cin;
using std::endl;
class Date
{
public:
//获取某年某月的天数
int GetMonthDay(int year, int month);
//全缺省的构造函数
Date(int year = 0, int month = 1, int day = 0);
//打印
void Print();
//析构、拷贝构造,赋值重载可以不写,默认生成的就够用,像Stack才需要自己写
//d+100
//赋值运算符重载
Date& operator+=(int day);
Date operator+(int day);
Date& operator-=(int day);
Date operator-(int day);
//返回两个日期之间相隔的具体天数
int operator-(const Date& d);
//++d -> d.operator++(&d)
Date& operator++();
//d++ -> d.operator++(&d,0)
//int参数不需要给实参,因为没用,它的作用是为了和前置++构成函数重载
Date operator++(int);
//运算符重载
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);
private:
int _year;
int _month;
int _day;
};
2.成员函数的实现:Date.cpp
2.1准确获取某年某月有多少天
inline int GetMonthDay(int year, int month)
{
//数组存储平年每个月的天数
static int dayArray[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
int i = dayArray[month];
if (month == 2 && ((year%4==0&&year%100!=0)||(year%400 == 0)))
{
i = 29;
}
return i;
}
2.2日期类构造函数
Date::Date(int year, int month, int day)//缺省参数在声明和实现两边只有一边可用
{
//检查日期的合法性
if (year>=0 &&month>0&&month<13 &&day>0&&day<=GetMonthDay(year,month))
{
_year = year;
_month = month;
_day = day;
}
else
{
//严格来说抛异常更好
cout << "非法日期" << endl;
cout << year << "年" << month << "月" << day << "日" << endl;
}
}
(补充)2.3日期类拷贝构造
Date::Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
2.4赋值运算符重载
Date& Date:: operator=(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
return *this; //这个可不能少,少了遇上连续赋值语句a=b=c会出错。
}
写拷贝构造和赋值时要加上const
![](https://i-blog.csdnimg.cn/blog_migrate/af04a59ee9b36d3081fbb15972c5ba62.png)
2.5+=运算符重载
考虑越界情况
- 如果
_day
加了整数以后,<=该月最大天数,则不需要修改,直接返回该日期.- 如果
_day
加了整数以后,>该月最大天数,则_day
减去新的月所拥有的最大天数,然后该月加1- 如果执行了第二步后,
_day
仍大于新的月所拥有天数,继续执行第二步,并且循环
//类似加法进位的规则:1.天满了,减去当前月的天数,月+1
//2.月满了,年+1,月置成1
Date& Date::operator+=(int day)
{
if (day < 0)
{
*this -= -day;
}
else
{
_day += day;
//天数不合法,不断进位使其合法
while (_day > GetMonthDay(_year, _month))
{
_day -= GetMonthDay(_year, _month);
_month++;
if (_month > 12)
{
++_year;
_month = 1;
}
}
}
return *this;
}
或者用+=复用+
Date& Date::operator+=(int day)
{
*this = *this +day;
return *this;
}
用+来复用+=
Date Date::operator+(int day)
{
Date ret(*this);
ret += day;
return ret;
}
两种复用的比较:第一种调用+有两次拷贝构造,调用+=没有拷贝构造;第二种调用+和+=都有两次拷贝构造
2.6+运算符重载
Date Date::operator+(int day)
{
Date ret(*this);
//复用operator+=
ret += day; //相当于ret.operator+=(day)
return ret;
}
2.7-=运算符重载
Date& Date::operator-=(int day)
{
if(day<0)
{
//_day += -day;
天数不合法,不断进位使其合法
//while (_day > GetMonthDay(_year, _month))
//{
// _day -= GetMonthDay(_year, _month);
// _month++;
// if (_month > 12)
// {
// ++_year;
// _month = 1;
// }
//}
//复用调用上面的函数
* this += -day;
}
else
{
/*_day -= day;
while (_day <= 0)
{
--_month;
if (_month == 0)
{
--_year;
_month = 12;
}
_day += GetMonthDay(_year, _month);
}*/
* this -= day;
}
return *this;
}
2.8-运算符重载
Date Date::operator-(int day)
{
Date tmp = *this;
tmp -= day;//tmp.operator
return tmp;
}
2.9前置++运算符重载
//++d -> d.operator++(&d)
Date& Date::operator++()
{
*this += 1;
return *this;
}
(补充)2.10前置--运算符重载
Date& Date::operator--()
{
*this -= 1;
return *this;
}
(补充)2.11后置-- 运算符重载
Date& Date::operator--(int) //这个int用于区分前置还是后置
{
Date tmp(*this);
*this -= 1;
return tmp;
}
2.12后置++运算符重载
//d++ -> d.operator++(&d,0)
//int参数不需要给实参,因为没用,它的作用是为了和前置++构成函数重载
Date Date::operator++(int)
{
Date tmp(*this);
*this += 1;
return tmp;
}
2.13>运算符重载
bool Date::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;
}
2.14==运算符重载
bool Date::operator==(const Date& d)
{
return _year = d._year
&& _month == d._month
&& _day == d._day;
}
2.15>=运算符重载
bool Date::operator>=(const Date& d)
{
return *this > d || *this == d;
}
2.16<运算符重载
bool Date::operator<(const Date& d)
{
return !(*this >= d);
}
2.17<=运算符重载
bool Date::operator<(const Date& d)
{
return !(*this >= d);
}
2.18!=运算符重载
bool Date::operator!=(const Date& d)
{
return !(*this == d);
}
2.19.计算两个日期之间的间隔天数,日期减去日期
//调用前面实现的各种函数来实现
int Date::operator-(const Date& d)
{
//效率差别不大的情况下,尽量选择可读性强的,简单的程序
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;
}
3.测试:Test.h
#include "Date.h"
void Test1()
{
Date d1(2021, 5, 25);
d1.Print();
Date d2(2021, 0, 0);
//d2.Print();
Date d3(2021, 2, 29);
d3.Print();
}
void Test2()
{
Date d1(2021, 5, 25);
d1.Print();
d1 += 3;
d1.Print();
d1 += 17;
d1.Print();
}
void Test3()
{
Date d1(2021, 5, 27);
d1 -= 120;
d1.Print();
Date d2(2021, 5, 27);
d2 -= -100;
d2.Print();
Date d3(2021, 5, 27);
d3 += 100;
d3.Print();
Date d4(2021, 5, 27);
d4 += -100;
d4.Print();
}
void Test4()
{
Date d1(2021, 5, 27);
//前置++和后置++都完成了++,不同的地方在于返回值不一样
//因为他们的运算符是一样的,函数名就是一样的,
//为了区分,对后置++做了特殊处理,加了一个参数,形成函数重载
Date ret1 = d1++;//d1.operator++(&d1)
ret1.Print();
d1.Print();
Date ret2 = ++d1;//d1.operator++(&d1,0)
ret2.Print();
d1.Print();
}
void Test5()
{
Date d1(2021, 5, 27);
Date d2(2021, 12, 31);
cout << d2 - d1 << endl;
cout << d1 - d2 << endl;
}
int main()
{
Test5();
return 0;
}