这是对于类和对象的练习篇,用c++来模拟完成日期计算器。
这其中需要我们完成:
- 日期 +- 天数后 得到的新日期
- 日期 - 日期 得到相差的天数
- 比较日期的大小
- 等 .....
- 具体如下头文件类中的成员函数
#pragma once #include<iostream> using namespace std; #include<assert.h> #include<math.h> class Date { public: // 获取某年某月的天数 int GetMonthDay(int year, int month); // 全缺省的 构造函数 Date(int year = 1900, int month = 1, int day = 1) { if (month <= 12 && month > 0 && day <= GetMonthDay(year, month)) { _year = year; _month = month; _day = day; } else { cout << "非法日期" << endl; assert(0); } } // 拷贝构造函数 // d2(d1) Date(const Date& d) { _year = d._year; _month = d._month; _day = d._day; } void Print() { cout << _year << ' ' << _month << ' ' << _day << endl; } // 赋值运算符重载 // d2 = d3 -> d2.operator=(&d2, d3) Date& operator=(const Date& d) { if (this != &d)//比较地址(比较地址比较简单),减少 d1=d1 这种赋值情况 { _year = d._year; _month = d._month; _day = d._day; } return *this; } // 日期+=天数 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; };
实现过程 (一些实现的细节已经注释):
- 日期类的 += 日期
int Date::GetMonthDay(int year, int month) { static int arr[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月闰年单独讨论 { return 29; } else { return arr[month]; } } //返回 引用可以减少拷贝的损耗 //其中返回 Date 类型还能帮助我们实现连续操作 Date& Date::operator+=(int day) { if (day < 0)//为了当传进来是-的天数也能使用 { *this -= (-day);//-= 在后面实现 return *this; } _day += day;//用进位的方法来算,先加上天数 while(_day > GetMonthDay(_year,_month))//如果天数大于该月的月数就进位 { _day -= GetMonthDay(_year, _month);//在进位后就需要把上月的天数剪掉 //注意这些应该写在后面 _month++; if (_month > 12)//当月到了12时也要进位 { _month = 1; _year++; } } return *this; }
- 日期类的 + 日期
Date Date::operator+(int day) { //我们在使用 + 时有时是不需要去改变值的 如 a + 2 ; a 并没有改变 Date tmp(*this);//创建一个临时变量 tmp += day;//对临时变量 += return tmp;//返回临时变量即可 //下面其实是一些重复的动作我们可以通过再次调用+= //tmp._day += day; //while (tmp._day > GetMonthDay(_year, _month)) //{ // tmp._day -= GetMonthDay(_year, _month); // //注意这些应该写在后面 // tmp._month++; // if (tmp._month > 12) // { // tmp._month = 1; // tmp._year++; // } //} //return tmp; }
-
日期类的 -= 日期
Date& Date::operator-=(int day) { if (day < 0)//同理当day < 0 时就相当于 += { *this += (-day); return *this; } _day -= day;//先减去一定的天数 while (_day <= 0)//不断的借位,只到借到正常的天数 { _month--; if (_month < 1) { _month = 12; _year--; } //注意此时day += 应该写在后面 因为是要向前借位 _day += GetMonthDay(_year, _month);//加上前一个月的月份,接一位 } return *this; }
-
日期类的-天数
Date Date::operator-(int day)//和 + 一样直接通过临时变量的传递即可 { Date tmp(*this); tmp -= day; return tmp; }
-
日期类的 ++
-
注意此时是要分 前置 和 后置
-
对于前置来说 我们就正常的写 运算符重载函数即可
-
而 对于 后置来说 写运算符重载函数时 需要一个参数来占位(与前置形成重载函数)
-
具体源码如下
Date& Date::operator++()//前置 ++ { *this += 1;//直接++即可 return *this; } Date Date::operator++(int) // 后置 ++ 通过一个参数来占位 构成函数重载来区分 { Date tmp(*this);// 因为是后置 ++ 所以用临时变量传回去之前前的值 *this += 1;//实则已经改变了 return tmp; }
-
-
日期类的 --
-
同样分前置和后置
-
就不过多赘述了,和++一样
-
具体如下:
Date& Date::operator--()//前置 { *this -= 1; return *this; } Date Date::operator--(int)//后置 { Date tmp(*this); *this -= 1; return tmp; }
-
-
日期类的比较 > >= == != < < = (总体来说较为简单
-
对于这类比较性的我们其实可以先写出 < 、== / >、== 其余的复用即可
-
具体如下
bool Date::operator>(const Date& d) { if (_year < d._year)//先判断是否小于,若否则是 等于(继续判断)或 大于(直接结束) { return false; } else if (_year == d._year && _month < d._month)//同理 { return false; } else if (_year == d._year && _month == d._month && _day < d._day) { return false; } else { return true; } } bool Date::operator==(const Date& d)//简单的判断 { return (_year == d._year && _month == d._month && _day == d._day); } bool Date::operator>=(const Date& d)//复用即可 { return *this > d || *this == d; //可以直接引用 > 和 == //if (_year < d._year) //{ // return false; //} //else if (_year == d._year && _month < d._month) //{ // return false; //} //else if (_year == d._year && _month == d._month && _day < d._day) //{ // return false; //} //else //{ // return true; //} } bool Date::operator <= (const Date& d) { return !(*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) { int tag = 1; Date Max(*this);//先确立大的为*this Date Min(d);//把 d 看成小的 if (Max < Min)//如果 Max < Min 就交换 { Min = *this; Max = d; tag = -1;// 交换后表示前面的值要小于后面的值 , 所以把 tag 置为负的 } int count = 0; while (Min < Max)//看看相差多少 ,逐一相加 { count++; ++Min; } return count * tag; }
-