运算符重载
1.重载的概念
C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。当您调用一个重载函数或重载运算符时,编译器通过把您所使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策。
2.运算符重载的形式
返回值类型 operator 需要重载的操作符 (参数列表)
C++中并不是所有的符号都可以被重载
可被重载的操作符
下面是可重载的运算符列表:
双目算术运算符 + (加),-(减),*(乘),/(除),% (取模)
关系运算符 ==(等于),!= (不等于),< (小于),> (大于>,<=(小于等于),>=(大于等于)
逻辑运算符 ||(逻辑或),&&(逻辑与),!(逻辑非)
单目运算符 + (正),-(负),*(指针),&(取地址)
自增自减运算符 ++(自增),–(自减)
位运算符 | (按位或),& (按位与),~(按位取反),^(按位异或),,<< (左移),>>(右移)
赋值运算符 =, +=, -=, *=, /= , % = , &=, |=, ^=, <<=, >>=
空间申请与释放 new, delete, new[ ] , delete[]
其他运算符 ()(函数调用),(下标[]),->(成员访问),(逗号)
下面是不可重载的运算符列表:
.:成员访问运算符
., ->:成员指针访问运算符
:::域运算符
sizeof:长度运算符
?::条件运算符
2.注意
- 不能通过其他符号来创建新的操作符 : 比如operator@
- 重载操作符必须有一个类类型或者枚举类型的操作数
- 用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不能改变其含义
- 作为类成员的重载函数,其形参看起来比操作数数目少1成员函数的操作符是因为成员函数默认的已经包含一个this指针
- 一般将算数操作符定义为非成员函数,将赋值运算符定义为成员函数
- 操作符定义为非类的成员函数时,一般将其定义为类的友元
- ==和!= 一般要成对进行重载
- 下标操作符[]: 一个非const成员并返回引用,一个是const成员并返回引用
- 解引用操作符: * , -> ,不显示任何参数
- 前置++/- 必须返回被增(减)量的引用,后缀式操作符必须返回旧值,并且应该是值返回而不是返回引用
输入输出操作符必须定义为类的友元函数
例子 :
#include <iostream>
using namespace std;
class Date
{
public:
Date(int y = 1998, int m = 2, int d = 15)
:year(y)
,month(m)
,day(d)
{}
Date(const Date& date)
:year(date.year)
,month(date.month)
,day(date.day)
{}
~Date(){}
Date& operator=(const Date& d)
{
year = d.year;
month = d.month;
day = d.day;
return *this;
}
friend Date& operator+(const Date&, const Date&);//双目运算符
friend bool operator==(const Date&, const Date&);//关系运算符
friend bool operator!=(const Date&, const Date&);
private:
int year;
int month;
int day;
};
Date& operator+(const Date& d1, const Date& d2)//双目运算符
{
Date d;
d.year = d1.year + d2.year;
d.month = d1.month + d2.month;
d.day = d1.day + d2.day;
return d;
}
bool operator==(const Date& d1, const Date& d2)//关系运算符
{
if (d1.year == d2.year)
{
if (d1.month == d2.month)
{
if (d1.day == d2.day)
return true;
}
}
return false;
}
bool operator!=(const Date& d1, const Date& d2)
{
return !(d1 == d2);
}
输入输出操作符
#include <iostream>
using namespace std;
class Date
{
public :
Date(int y = 1998, int m = 2, int d = 15)
:year(y)
,month(m)
,day(d)
{}
friend ostream& operator<<(ostream&, const Date&);
private :
int year;
int month;
int day;
};
ostream& operator<<(ostream& os, const Date& d)
{
os << d.year << " " << d.month << " " << d.day;
return os;
}
int main()
{
Date d1;
cout << d1;
return 0;
}
输出结果
注意 :
在对操作符进行重载时,从左到右传参的顺序就是操作符的重载完成之后参数的位置,比如之前的对输出操作符<<进行重载时将输出流ostream与const Date& 写反,则在实例化调用的过程中也需要写成d1<
#include <iostream>
using namespace std;
class Date
{
public :
Date(int y = 1998, int m = 2, int d = 15)
:year(y)
,month(m)
,day(d)
{}
friend ostream& operator<<( const Date&, ostream&);
private :
int year;
int month;
int day;
};
ostream& operator<<(const Date& d, ostream& os)//在此处的参数传递与之前的顺序刚好相反
{
os << d.year << " " << d.month << " " << d.day;
return os;
}
int main()
{
Date d1;
d1<<cout;//输出的时候要按照和传参的顺序一致
return 0;
}
运行结果