导读
1. 为什么需要运算符重载
一般的运算符只能对于内置类型进行运算,或是比较大小,但是如果我们想要对自定义类型进行运算,就要调用对应的运算符重载
2.运算符重载的特点
- 运算符重载函数是特殊的函数,名字由operator和要定义的符号构成
- 运算符重载函数参数个数和和该运算符的运算对象一样多。二元运算符左侧对象传给第一个参数,右侧传给第二个参数
- 如果运算符重载函数是成员函数,第一个运算对象传给隐式的this指针
常见运算符实现
这里以日期类为例实现
class Date
{
private:
int _year;
int _month;
int _day;
};
赋值运算符(=)
- 检查是否是自我赋值,即当前对象和要赋值的对象是否是同一个对象。如果是同一个对象,则直接返回当前对象,避免不必要的操作。
- 这里和拷贝构造函数类似,若未显示实现运算符重载函数,编译器会自动生成。自动生成的赋值运算符重载函数只能完成浅赋值,如果类中有需要申请资源的变量,就需要自己显示完成赋值运算符重载函数
- 返回类类型的引用,以避免不必要的拷贝
Date& Date::operator=(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
return *this;
}
比较运算符(< ,>,==,!=,>=,<=)
//// >运算符重载
bool Date::operator>(const Date& d)const
{
if (_year >= d._year)
{
if (_year > d._year)
{
return true;
}
else {
if (_month >= d._month)
{
if (_month > d._month)
return true;
else
{
if (_day > d._day)
return true;
}
}
}
}
return false;
}
//// ==运算符重载
bool Date::operator==(const Date& d)const
{
return _year == d._year && _month == d._month && _day == d._day;
}
在这里,只要实现出==和<,其他比较运算符重载都可以复用这两个运算符函数,比如
bool Date::operator >= (const Date& d)const
{
return *this > d && *this == d;
}
加号运算符重载(+)
//获取当月天数
inline int Date::GetMonthDay(int year, int month)const
{
static int a[13] = { -1,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 a[month];
}
//// 日期+=天数
Date& Date::operator+=(int day)
{
if (day < 0)
*this -= (-day);
_day += day;
while (_day > GetMonthDay(_year, _month))
{
_day -= GetMonthDay(_year, _month);
_month++;
if (_month == 13)
{
_month = 1;
_year++;
}
}
return *this;
}
//
//// 日期+天数
Date Date::operator+(int day)const
{
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;
}
<<和>>
- 重载<<和>>时,需要重载成全局函数,因为重载成成员函数时,this指针默认在第一个形参位置,调用时就变成了(对象<<cout),不符合习惯
ostream& operator<<(ostream& out, const Date& d)
{
out << d._year<<"/" << d._month <<"/" << d._day;
return out;
}
istream& operator>>(istream& in, Date& d)
{
in >> d._year >> d._month >> d._day;
return in;
}
- 这里可以把函数设成Date类的友元函数,方便访问类的成员
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& out, Date& d);