从零开始学C++之c++类和对象<下>
1.赋值运算符重载
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
注意事项:
- 不能通过连接其他符号来创建新的操作符:比如operator@;
- 重载操作符必须有一个类类型或者枚举类型的操作数;
- 用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不能改变其含义;
- 作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的,操作符有一个默认的形参this,限定为第一个形参;
- .* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。
赋值运算符主要有四点:
- 参数类型
- 返回值
- 检测是否自己给自己赋值
- 返回*this
- 一个类如果没有显式定义赋值运算符重载,编译器也会生成一个,完成对象按字节序的值拷贝。
- 成员函数都会有一个隐含的this指针,运算符重载函数作为成员函数是参数列表中显式定义的参数个数,需要比实际的参数少一个
- 左操作数是this指向的调用函数的对象
- 如果需要进行连续赋值,返回值类型不能为空,返回类型应该为当前类型
- . 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。
//==运算符重载:
//函数名:operator==
bool operator==(const Data& d1, const Data& d2)
{
}
2.设计一个日期类
#pragma once
#include <iostream>
using namespace std;
class Date
{
private:
int _year;
int _month;
int _day;
int GetMonthDays(int year, int month)const;//获取某个月的天数
public:
Date()
: _year(1900)
, _month(1)
, _day(1)
{
}
Date(int year, int month, int day);// 构造函数
Date(const Date& d); // 拷贝构造函数
~Date()
{
} // 析构函数
int GetYear()const; // 返回年份
int GetMonth()const; // 返回月份
int GetDay()const; // 返回天数
void Print()const; // 输出日期
bool IsLeapYear()const; // 判断当前对象年是否是闰年
bool IsLeapYear(const int y)const; // 判断指定年份是否是闰年
// 操作符重载部分
// 天数 + 日期
friend Date operator+(const int d, const Date date);
// 日期 + 天数
friend Date operator + (const Date date, const int d);
// 前置 ++
friend Date& operator ++ (Date& date);
// 后置 ++ 多一个int参数与前置区别
friend Date operator ++ (Date& date, int);
// 重载 +=
friend Date operator +=(Date& date, const int d);
// 日期 - 天数
friend Date operator - (const Date date, const int d);
// 天数 - 日期
friend Date operator - (const int d, const Date date);
// 前置 --
friend Date& operator -- (Date& date);
// 后置 --
friend Date operator -- (Date& date, int);
// 重载 -=
friend Date operator -=(Date& date, const int d);
// 日期 - 日期
friend int operator - (const Date a, const Date b);
// 重载比较操作符
friend bool operator< (const Date a, const Date b);
friend bool operator<= (const Date a, const Date b);
friend bool operator> (const Date a, const Date b);
friend bool operator>= (const Date a, const Date b);
friend bool operator== (const Date a, const Date b);
friend bool operator!= (const Date a, const Date b);
// 重载输出运算符 <<
friend ostream& operator <<(ostream& _out, const Date& date);
// 重载输入运算符 >>
friend istream& operator >> (istream& _out, Date& date);
};
实现:
#include "Date.h"
//构造函数
Date::Date(int year = 1900,int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{
//检测年份月份天数的合法性
if ( year<= 0 ||
(month<=0 || month>12) ||
(day <= 0 || day>GetMonthDays(year, month)) )
{
_year = 1900;
_month = 1;
_day = 1;
}
}
//拷贝构造函数
Date::Date(const Date& d)
{
_year = d. _year;
_month = d. _month;
_day = d. _day;
}
//获取某月中的天数
int Date::GetMonthDays(int year, int month)const
{
// a[1] - a[12] 表示非闰年每月天数
int a[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
// 二月份天数做特殊处理 平年28 闰年29天
if (month == 2)
{
a[2] += IsLeapYear(year);
}
return a[month];
}
// 返回年份
int Date::GetYear()const
{
return _year;
}
// 返回月份
int Date::GetMonth()const
{
return _month;
}
// 返回天数
int Date::GetDay()const
{
return _day;
}
// 输出日期
void Date::Print()const
{
cout << _year << " 年 " << _month << " 月 " << _day << " 日 " <<endl;
}
// 判断当前年是否是闰年
bool Date::IsLeapYear()const
{
if ( _year%400 == 0 || ( _year%4==0 && _year%100!=0))
{
return true;
}
return false;
}
// 判断指定年份是否是闰年
bool Date::IsLeapYear(const int year)const
{
if (year%400 == 0 || (year%4==0 && year%100!=0))
{
return true;
}
return false;
}
// 操作符重载部分
// 天数 + 日期
Date operator+(const int d, const Date date)
{
Date tmpDate = date;
if (0 == d) return date; // 加的天数为0 返回本身的值
// 获取当前对象对应月份的天数
int days;
if (d > 0)
{
tmpDate. _day += d;
while (tmpDate. _day > (days = tmpDate.GetMonthDays(tmpDate. _year, tmpDate. _month))) //加天数后对不合理值处理
{
//2010.3.12 + 30 2012.3.42 > 31 2012.4.42 - 31
//减去该月的天数
tmpDate. _day -= days;
tmpDate. _month ++; // 月份增加一个月
if (tmpDate. _month > 12) //处理月份不合理
{
tmpDate. _year ++;
tmpDate. _month = 1; //超过12后年份++ 月份置1
}
}
}
else
{
return date - (0 - d);
}
return tmpDate;
}
// 日期 + 天数
Date operator + (const Date date, const int d)
{
return d + date;
}
// 前置 ++
Date& operator ++ (Date& date)
{
date = date + 1;
return date;
}
// 后置 ++ 多一个int参数与前置区别
Date operator ++ (Date& date, int)
{
Date temp = date;
date = date + 1;
return temp;
}
// 重载 +=
Date operator +=(Date& date, const int d)
{
date = date + d;
return date;
}
// 日期 - 天数
Date operator - (const Date date, const int d)
{
Date tempDate = date;
if (0 == d) return date;
if ( d>0 )
{
tempDate. _day -= d;
while (tempDate. _day <= 0)
{
--tempDate. _month;
if (tempDate. _month == 0)
{
--tempDate. _year;
tempDate. _month = 12;
}
tempDate. _day += tempDate.GetMonthDays(tempDate. _year, tempDate. _month);
}
}
else
{
return date + ( - d);
}
return tempDate;
}
// 天数 - 日期
Date operator - (const int d, const Date date)
{
return date - d;
}
// 前置 --
Date& operator -- (Date& date)
{
date = date - 1;
return date;
}
// 后置 --
Date operator -- (Date& date, int)
{
Date temp = date;
date = date - 1;
return temp;
}
// 重载 -=
Date operator -=(Date& date, const int d)
{
date = date - d;
return date;
}
// 日期 - 日期
int operator - (const Date a, const Date b)
{
int sumDay = 0;
if (a==b)
{
return 0;
}
else if(a>b)
{
Date temp = b;
while (temp!=a)
{
temp++;
sumDay++;
}
}
else // a<b
{
Date temp = a;
while (temp!=b)
{
temp++;
sumDay++;
}
}
return sumDay;
// 2016.1.1 - 2015.12.20
}
//重载比较操作符部分
// 判相等
bool operator== (const Date a, const Date b)
{
// 同年同月同日
return (a. _year == b. _year && a. _month == b. _month && a. _day == b. _day);
}
// 判不等
bool operator!= (const Date a, const Date b)
{
// 对判相等取反即可 a和b相等时 取反 不相等判断为假
return !(a==b);
}
// 判小于
bool operator< (const Date a, const Date b)
{
//先处理不小于 2016 10 29 2016 10 29 同年看月 同年同月看日
if (a. _year > b. _year||
(a. _year == b. _year && a. _month > b. _month)||
(a. _year == b. _year && a. _month == b. _month && a. _day >= b. _day)
)
{
return false;
}
return true;
}
// 判小于等于
bool operator<= (const Date a, const Date b)
{
if (a<b ||a==b)
{
return true;
}
return false;
}
// 判大于
bool operator> (const Date a, const Date b)
{
return !(a<=b);
}
// 判大于等于
bool operator>= (const Date a, const Date b)
{
if (a>b || a==b)
{
return true;
}
return false;
}
// 重载输出运算符 <<
std::ostream& operator<<(ostream& _out, const Date& date)
{
_out << date.GetYear() << " 年 " << date.GetMonth() << " 月 " << date.GetDay() << " 日 " <<endl;
return _out;
}
// 重载输入运算符 <<
std::istream& operator >> (istream& _input, Date& date)
{
int year = 0,month = 0,day = 0;
cin >> year >> month >> day;
Date temp(year,month,day);
date = temp;
return _input;
}
测试:
#include "Date.h"
int main()
{
Date d1;
d1.Print();
cout<<"1.对日期++或--:"<<endl;
Date d2(2016, 10 , 1);
d2.Print();
++d2;
d2.Print();
--d2;
d2.Print();
d2--;
d2.Print();
d2++;
d2.Print();
cout <<" 2.对日期+=和-=和对日期减一个天数"<< endl;
Date d3(2016,1,1);
d3.Print();
d3 += 10;
d3.Print();
d3 -= 10;
d3.Print();
d3 = d3 - 3;
d3.Print();
bool state;
cout<<"3.两日期比较"<<endl;
Date d4(2016,10,9);
Date d5(2016,10,10);
state = d4<d5;
cout << state << endl;
cout<<"4.两日期相减"<<endl;
Date d6(2008,4,1);
Date d7(2016,1,1);
cout << d6 - d7<<endl;
cout << d7 - d6 << endl;
return 0;
}