提示:以下是本篇文章正文内容
一、时间类
1.日期的比较(重载运算符)
(1).==
bool operator==(const Date& y);
bool Date::operator==(const Date& y)
{
return _year == y._year
&& _month == y._month
&& _day == y._day;
}
(2).!=
bool operator!=(const Date& y);
bool Date::operator!=(const Date& y)
{
return !(*this == y);//复用==,相反就是不等于,后面的我们可以采用复用前面我们写的代码
}
(3).>
bool operator>(const Date& y);
bool Date::operator>(const Date& y)
{
if (_year > y._year)
{
return true;
}
else if (_year == y._year && _month > y._month)
{
return true;
}
else if (_year == y._year && _month == y._month && _day > y._day)
{
return true;
}
return false;
}
(4).<
bool operator<(const Date& y);
bool Date::operator<(const Date& y)
{
return !(*this >= y);//复用>=
}
(5).>=
bool operator>=(const Date& y);
bool Date::operator>=(const Date& y)
{
return *this > y || *this == y;
}
(6).<=
bool operator<=(const Date& y);
bool Date::operator<=(const Date& y)
{
return !(*this > y);
}
(2)日期的加减
(1)-
int operator-(const Date& d);
int Date::operator-(const Date& d)//两个日期相减,我们可以用最小的那个日期不断加一天,直到等于最大的那个日期就停止。while控制循环,n就是它们之间相差的天数。flag用来标记如果小的日期减大的日期就是-,大的减小的就是+
{
// 假设左大右小
int flag = 1;
Date max = *this;
Date min = d;
// 假设错了,左小右大
if (*this < d)
{
max = d;
min = *this;
flag = -1;
}
int n = 0;
while (min != max)
{
++min;//复用++,Date& Date::operator++()
++n;//累加的天数
}
return n * flag;
}
(2)+=
Date& operator+=(int 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)//如果月份=13,就年++
{
_year++;
_month = 1;
}
}
return *this;
}
//Date& Date::operator+=(int day)//我们不建议这种方式虽然复用+,不过它要拷贝3次对象,*this+day中有2次,然后返回的对象又赋值给*this又一次,效率比较低
//{
// //Date d = *this + day;//拷贝构造
// //*this = d;
//
// *this = *this + day;
// return *this;
//}
(3)+
Date operator+(int day);
Date Date::operator+(int day)//,拷贝2次对象,返回值临时对象拷贝一次,拷贝对象一次
{
Date tmp(*this);//+不改变对象自己,所以拷贝一个和自己相同对象
tmp += day;
return tmp;
}
//方式2
//Date Date::operator+(int day)//拷贝2次对象
//{
// Date tmp(*this);
//
// tmp._day += day;
// while (tmp._day > GetMonthDay(tmp._year, tmp._month))
// {
// tmp._day -= GetMonthDay(tmp._year, tmp._month);
//
// ++tmp._month;
//
// if (tmp._month == 13)
// {
// tmp._year++;
// tmp._month = 1;
// }
// }
//
// return tmp;
//}
(4)-=
Date& operator-=(int day);
Date& Date::operator-=(int day)
{
if (day < 0)
{
return *this += (-day);
}
_day -= day;
while (_day <= 0)
{
--_month;
if (_month == 0)
{
--_year;
_month = 12;
}
_day += GetMonthDay(_year, _month);//获取月份(在下面的Date.c中定义)
}
return *this;
}
(5)-
Date operator-(int day)
Date Date::operator-(int day)
{
Date tmp(*this);
tmp -= day;
return tmp;
}
(6)前缀++
Date& operator++();
Date& Date::operator++()
{
*this += 1;
return *this;
}
(7)后置++
Date operator++(int);
Date Date::operator++(int)//C++为了不和前置++,冲突,参数有个类型int
{
Date tmp(*this);
*this += 1;
return tmp;
}
(8)前置--
Date& operator--();
Date& Date::operator--()
{
*this -= 1;
return *this;
}
(9)后置--
Date operator--(int);
Date Date::operator--(int)
{
Date tmp(*this);
*this -= 1;
return tmp;
}
(3)重载输入输出<<和>>
1. ostream& operator<<(ostream& out, const Date& d);
2. istream& operator>>(istream& in, Date& d);
这里的输入输出重载,是全局函数不是该类的成员函数,只是把它声明为该类的友元函数。这里我们为什么不可以重载为成员函数呢?
因为如果是成员函数,它会有隐藏的this指针,会占据参数的第一个位置,使用的时候感觉怪怪的
//这里的输入输出重载,是全局函数不是该类的成员函数,只是把它声明为该类的友元函数(需要在类里面申明)。
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& in, Date& d);
ostream& operator<<(ostream& out, const Date& d)//返回值为输出流对象,保证连续输出
{
out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
return out;
}
istream& operator>>(istream& in, Date& d)
{
in >> d._year >> d._month >> d._day;
return in;
}
。
二、时间类代码
1.Date.h
#include<iostream>
#include<assert.h>
using namespace std;class Date
{
public:
Date(int year = 1, int month = 1, int day = 1);//构造函数,数据类型是内置类型,我们可以不写析构函数,编译器会在最后调用默认生成的析构函数void Print();
int GetMonthDay(int year, int month);//获取月份的天数bool operator==(const Date& y);
bool operator!=(const Date& y);
bool operator>(const Date& y);
bool operator<(const Date& y);
bool operator>=(const Date& y);
bool operator<=(const Date& y);int operator-(const Date& d);
Date& operator+=(int day);
Date operator+(int day);
Date& operator-=(int day);
Date operator-(int day);Date& operator++();
Date operator++(int);Date& operator--();
Date operator--(int);
private:
int _year;
int _month;
int _day;
};
2.Date.c
#include "Date.h"
Date::Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;if (_year < 1 ||
_month < 1 || _month > 12 ||
_day < 1 || _day > GetMonthDay(_year, _month))
{
//assert(false);
Print();
cout << "日期非法" << endl;
}
}void Date::Print()
{
cout << _year << "/" << _month << "/" << _day << endl;
}bool Date::operator==(const Date& y)
{
return _year == y._year
&& _month == y._month
&& _day == y._day;
}// d1 != d2
bool Date::operator!=(const Date& y)
{
return !(*this == y);
}bool Date::operator>(const Date& y)
{
if (_year > y._year)
{
return true;
}
else if (_year == y._year && _month > y._month)
{
return true;
}
else if (_year == y._year && _month == y._month && _day > y._day)
{
return true;
}return false;
}bool Date::operator>=(const Date& y)
{
return *this > y || *this == y;
}bool Date::operator<(const Date& y)
{
return !(*this >= y);
}bool Date::operator<=(const Date& y)
{
return !(*this > y);
}int Date::GetMonthDay(int year, int month)
{
assert(year >= 1 && month >= 1 && month <= 12);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)))
return 29;return monthArray[month];
}// d1 += 100
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+(int day)
{
Date tmp(*this);
tmp += day;return tmp;
}
Date& Date::operator-=(int day)
{
if (day < 0)
{
return *this += (-day);
}_day -= day;
while (_day <= 0)
{
--_month;
if (_month == 0)
{
--_year;
_month = 12;
}_day += GetMonthDay(_year, _month);
}return *this;
}Date Date::operator-(int day)
{
Date tmp(*this);
tmp -= day;return tmp;
}
// ++d1
Date& Date::operator++()
{
*this += 1;
return *this;
}// d1++
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;
}// d1 - d2
int Date::operator-(const Date& d)
{
// 假设左大右小,保证max是日期大的那个,min是小的那个
int flag = 1;//标记
Date max = *this;
Date min = d;// 假设错了,左小右大
if (*this < d)
{
max = d;
min = *this;
flag = -1;
}int n = 0;
while (min != max)
{
++min;
++n;
}return n * flag;
}
3.test.c
#include "Date.h"
void TestDate1()
{
Date d1(2023, 10, 24);
d1.Print();Date ret1 = d1 - 100;
ret1.Print();Date ret2 = d1 - 10000;
ret2.Print();Date ret3 = d1 + 100;
ret3.Print();Date ret4 = d1 + 10000;
ret4.Print();
}void TestDate2()
{
Date d1(2023, 10, 24);
d1.Print();++d1;
d1.operator++();
d1.Print();d1++;
d1.operator++(10);
d1.operator++(1);
d1.Print();
}void TestDate3()
{
Date d1(2023, 10, 24);
d1.Print();
Date d2(2024, 5, 5);
d2.Print()
cout << d2 - d1 << endl;
}
void TestDate4()
{
Date d1(2023, 10, 24);
d1 += -100;d1.Print();
}int main()
{
TestDate3();return 0;
}
总结
在写类的时候,我们尽量把相同的代码放在一起,同时我们分别把申明和源代码分开写在不同文件中,方便管理。为简化代码,我们可以考虑代码的复用,要注意的是复用的时候,可以考虑一下比较优化的复用,比如复用+=,方式二,拷贝对象有三次就不选择,如果是链表的话,加起来太多了。