前言:C++中最为重要的就是类与对象,通过日期类的实现可以帮助我们更加深刻地理解和掌握这一重要内容,当然要想彻底掌握类与对象,离不开长时间的联系。今后我将更新STL源码分析,将会对类与对象有更深刻的理解,希望大家关注!
1.前提准备
目的:我们希望日期类程序能够起到日期计算器的作用,一方面可以计算两个日期之间相差的天数;另一方面可以计算某一日往后若干天是什么日期。
注意事项:
1.类与对象是封装的概念,每一个类中的_year,_month,_day是私有的。
2.通过运算符重载,可以直接实现两个日期类之间的减法,也可以直接实现一个日期类加减一个整型天数。
3.通过运算符重载,可以直接输入和输出一个日期类,但要注意使用友元函数。
2.代码呈现
1.类的声明
// 类里面短小函数,适合做内联的函数,直接是在类里面定义的
class Date
{
// 友元
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& in, Date& d);
public:
Date(int year = 1900, int month = 1, int day = 1);
void Print() const;
int GetMonthDay(int year, int month) const;
bool operator==(const Date& d) const;
bool operator!=(const Date& d) const;
bool operator<(const Date& d) const;
bool operator<=(const Date& d) const;
bool operator>(const Date& d) const;
bool operator>=(const Date& d) const;
Date& operator+=(int day);
Date operator+(int day) const;
Date& operator-=(int day);
Date operator-(int day) const;
// d1 - d2;
int operator-(const Date& d) const;
// ++d1
Date& operator++();
// d1++
// int参数 仅仅是为了占位,跟前置重载区分
Date operator++(int);
// --d1 -> d1.operator--()
Date& operator--();
// d1-- -> d1.operator--(1)
Date operator--(int);
//void operator<<(ostream& out);
private:
int _year;
int _month;
int _day;
};
注意:当不需要改变类中数据值时,我们通常加入const关键词声明!
2.输入输出运算符重载
inline ostream& operator<<(ostream& out, const Date& d)
{
out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
return out;
}
inline istream& operator>>(istream& in, Date& d)
{
in >> d._year >> d._month >> d._day;
return in;
}
注意:因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作 数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。所以要将operator<<重载成全局函数。但又会导致类外没办法访问成员,此时就需要友元来解决operator>>同理。
3.计算每一个月的天数
int Date::GetMonthDay(int year, int month) const
{
assert(month > 0 && month < 13);
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;
}
else
{
return monthArray[month];
}
}
4.构造函数
Date::Date(int year, int month, int day)
{
if (month > 0 && month < 13
&& (day > 0 && day <= GetMonthDay(year, month)))
{
_year = year;
_month = month;
_day = day;
}
else
{
cout << "fail" << endl;
}
}
5.打印函数(与输出运算符重载功能一致)
void Date::Print() const
{
cout << _year << "/" << _month << "/" << _day << endl;
}
6.比较运算符重载
bool Date::operator==(const Date& d) const
{
return _year == d._year
&& _month == d._month
&& _day == d._day;
}
// d1 < d2
bool Date::operator<(const Date& d) const
{
return _year < d._year
|| (_year == d._year && _month < d._month)
|| (_year == d._year && _month == d._month && _day < d._day);
}
// d1 <= d2
bool Date::operator<=(const Date& d) const
{
return *this < d || *this == d;
}
// d1 > d2
bool Date::operator>(const Date& d) const
{
return !(*this <= d);
}
bool Date::operator>=(const Date& d) const
{
return !(*this < d);
}
bool Date::operator!=(const Date& d) const
{
return !(*this == d);
}
7.加减运算符重载
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 == 13)
{
++_year;
_month = 1;
}
}
return *this;
}
// d1 + 100
Date Date::operator+(int day) const
{
Date tmp(*this);
tmp += day;
return tmp;
}
Date& Date::operator-=(int day)
{
if (day < 0)
{
*this += -day;
return *this;
}
_day -= day;
while (_day <= 0)
{
--_month;
if (_month == 0)
{
--_year;
_month = 12;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
Date Date::operator-(int day) const
{
Date tmp(*this);
tmp -= day;
return tmp;
}
8.++、--运算符重载
// ++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;
}
// d1-- -> d1.operator--(1)
Date Date::operator--(int)
{
Date tmp(*this);
*this -= 1;
return tmp;
}
注意:前置++、--与后置++、--的区别;后置多了一个形参与前置形成对比。
9.计算两个日期相差的天数
// d1 - d2;
int Date::operator-(const Date& d) const
{
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;
}