目录
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;
- }