1,主要内容
多采用符号重载的方法对日期类进行基本操作。包括日期的计算和
2,操作符重载为成员函数
当一个操作符被重载为成员函数时,在使用这个操作符时会隐式的把操作符左边的类对象的地址作为第一个参数传入函数,
例如:一个对象t1, t1+1, 就等于operator+(&t1 , 1)
对于前置++,--运算符,因为是单目运算符,并不一定去寻找操作符左边的对象,而是右边的对象。
3,日期类的声明
#ifndef __DATE_H__
#define __DATE_H__
#include<iostream>
using namespace std;
class Date
{
friend ostream& operator<<(ostream& _cout,Date& d);
public:
Date(int year=2000,int month=12,int day=13);//构造函数
Date(const Date& d);//拷贝构造函数
void Print();
//判断一年是不是闰年
bool IsLLeapYear(int year);
//当前年的一个月份共有几个天
int GetMonthDay(int year,int month);
// 当前日期days天后是什么日期?
Date operator+(int days);
// 当前日期days天前是什么日期?
Date operator-(int days);
// 两个日期之间差了多少天?
int operator-(const Date& d);
// 日期比大小
bool operator>(const Date& d);
bool operator<(const Date& d);
bool operator==(const Date& d);
bool operator!=(const Date& d);
Date& operator=(const Date& d);
// 前置++
Date& operator++();
// 后置++
Date operator++(int);
// 前置--
Date& operator--();
// 后置++
Date operator--(int);
private:
int _year;
int _month;
int _day;
};
4,日期类成员函数,输出流友员函数的定义
#include"Date.h"
Date::Date(int year,int month,int day)
:_year(year)
,_month(month)
,_day(day)
{}
Date::Date(const Date& d)
:_year(d._year)
,_month(d._month)
,_day(d._day)
{}
void Date::Print()
{
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
}
//判断一年是不是闰年
bool IsLeapYear(int year)
{
if(year%4==0&&year%100!=0||year%400==0)
{
return true;
}
return false;
}
//当前年的一个月份共有几个天
int Date:: GetMonthDay(int year,int month)
{
int month_arr[12]={31,28,31,30,31,30,31,31,30,31,30,31};
if(month==2 && IsLeapYear(year))
{
month_arr[1]=29;
}
return month_arr[month-1];
}
// 当前日期days天后是什么日期?
Date Date::operator+(int days)
{
Date ret=*this;
int sum_day=ret._day+days;
while(sum_day>GetMonthDay(ret._year,ret._month))
{
sum_day-=GetMonthDay(ret._year,ret._month);
ret._month++;
if(ret._month>12)
{
ret._year++;
ret._month%=12;
}
}
ret._day=sum_day;
return ret;
}
//
//
//当前日期days天前是什么日期?
Date Date:: operator-(int days)
{
Date ret=*this;
int sub_day=ret._day-days;
if(sub_day<0)
{
ret._month--;
if(ret._month<1)
{
ret._year--;
ret._month=12;
}
sub_day+=GetMonthDay(ret._year,ret._month);
}
ret._day=sub_day;
return ret;
}
// 两个日期之间差了多少天?
int Date:: operator-(const Date& d)
{
Date mindate=d;
Date maxdate=*this;
int flag=1;
int days=0;
if(*this<d)
{
mindate=*this;
maxdate=d;
flag=-1;
}
while(1)
{
if(mindate+days==maxdate)
{
break;
}
days++;
}
return days*flag;
}
// 日期比大小
bool Date:: operator>(const Date& d)
{
if((_year>d._year) ||
((_year==d._year)&&(_month>d._month)) ||
((_year==d._year)&&(_month==d._month)&&(_day>d._day)))
{
return true;
}
return false;
}
bool Date::operator<(const Date& d)
{
if((_year<d._year) ||
((_year==d._year)&&(_month<d._month)) ||
((_year==d._year)&&(_month==d._month)&&(_day<d._day)))
{
return true;
}
return false;
}
bool Date::operator==(const Date& d)
{
if((_year==d._year)&&(_month==d._month)&&(_day==d._day))
{
return true;
}
return false;
}
bool Date:: operator!=(const Date& d)
{
return !(*this==d);
}
Date& Date::operator=(const Date& d)
{
_year=d._year;
_month=d._month;
_day=d._day;
return *this;//为了实现连续赋值 a=b=c 是先将c给b 再将b给a
}
前置++
Date& Date:: operator++()
{
_day+=1;
return *this;
}
//
// 后置++
Date Date:: operator++(int)//用这个参数来进行与前置++进行区分,系统自动传0
//单目运算符,不必考虑参数位置,系统会传入this指针
{
Date temp(*this);
_day+=1;
return temp;
}
//
// 前置--
Date& Date:: operator--()
{
_day-=1;
return *this;
}
//
// 后置--
Date Date:: operator--(int)
{
Date temp(*this);
_day-=1;
return temp;
}
ostream& operator<<(ostream& _cout,Date& d)
{
cout<<d._year<<"-"<<d._month<<"-"<<d._day;
return _cout;
}
5,为什么不能重载流输入>>操作符和流输出操作符<<为成员函数,只能重载为友员函数和普通函数?
答:将流输出<<操作符重载为成员函数 注:ostream是输出流类,_cout是一个类对象
ostream& Date:: operator<<(ostream& _cout)
{
_cout<<_year<<"-"<<_month<<"-"<<_day;
return _cout;
进行测试
#include"Date.h"
int main()
{
Date d (2000,2,2);
cout<<d;
return 0;
}
结果失败,
重新测试
#include"Date.h"
int main()
{
Date d (2000,2,2);
d<<cout;
return 0;
}
结果正确
分析原因:
当把输入流函数重载为成员函数时,参数列表已经固定了,先将左操作数地址作为第一个参数,右操作数作为第二个参数
所以正确的使用方式是 d<<cout , 但我们的习惯是cout<<d, 所以不能定义为成员函数,可通过定义为友元函数完成目标