原文链接:http://blog.csdn.net/lyh__521/article/details/49592975
基本概念
重载的运算符是具有特殊名字的函数:
(1) 名字由关键字 operator 和其后要定义的运算符号(+、-、/、* 等组成);
(2) 和其他的函数一样,也包含返回类型、参数列表以及函数体。
- 对于二元运算符来说,左侧运算对象传递给第一个参数,而右侧运算符传递给第二个参数。当一个重载的运算符函数是成员函数时,隐式的 this 绑定到左侧运算对象。因此,成员运算符函数的(显式)参数数量比运算对象的数量少一个。
- 除了重载运算符 operator() 之外,其他重载运算符不能含有默认实参。
- 运算符函数或者是类的成员,或者至少含有一个类类型的参数。
//例如
int operator+(int,int);
//错误,不能为int重定义内置的运算符
- 我们可以重载大部分的运算符,但我们只能重载已有的运算符,不能发明新的运算符合。
- 对于重载的运算符来说,其优先级和结合律与对应的内置运算符保持一致。例如重载的‘+’的优先级也是低于‘/’的。
可以被重载的运算符:
不能被重载的运算符:
运算符函数的调用
- 调用成员运算符函数
以下的两条语句都等价的调用了成员函数 operator+= , 将this 绑定到data1 的地址,将data2 作为实参传入了函数。
data1 += data2; //表达式的方式调用
data1.operator += (data2); //等价的普通函数调用方式
- 非成员运算符函数的调用
以下的两条语句都等价的调用了非成员函数 operator+ ,传入data1 作为第一个实参,传入data2 作为第二个实参。
data1 + data2; //表达式方式调用
operator+(data1,data2); //等价的函数调用
某些运算符不应该被重载
注意: 是不应该,并不是不能。
因为某些运算符指定了运算对象求值的顺序。使用重载的运算符本质上是一次函数调用,所以这些关于运算对象求值顺序的规则无法应用到重载的运算符上。
逻辑与、逻辑或 和 逗号运算符
的对象求值顺序规则无法保留下来。&& 和 || 运算符
的重载版本无法保留内置运算符的短路求值属性。比如:|| 运算符在运算的时候,如果第一个表达式为真,则不用再计算第二个表达式,但是重载的||运算符总会计算两个表达式,这让用户在使用的时候可能会突然感觉一直习惯的求值规则不再适用了。逗号运算符 和 取地址运算符
: C++ 赋予了这两种运算符特殊的含义,如果重载将会导致他们的行为异于常态。
使用与内置类型一致的含义
- 如果类执行IO操作,定义的移位运算符应与内置类型的IO保持一致。
- 检查相等性,则定义 operator==; 这时候,通常也应该定义 operator != 。
- 如果类包含一个单序的比较操作,则定义 operator< 等关系操作。
- 返回类型通常应与内置版本的返回类型兼容:逻辑运算符和关系运算符返回bool,算术运算符返回类类型的值,赋值运算符和复合赋值运算符则应该返回左侧运算对象的一个引用。
选择成员还是非成员函数
- 赋值 = 、下标[ ]、调用( )、和成员访问-> 运算符必须是成员。
- 复合赋值运算符一般来说应该是成员。
- 改变对象状态的运算符或者与给定类型密切相关的运算符,如递增、递减和解引用运算符,通常应该是成员。
- 具有对称性的运算符可能转换任意一端的运算对象,例如算术、相等性、关系和位运算符等,通常应该是普通的非成员函数。
例如,如果将 + 定义为string 类的成员函数,下面的使用将会出现问题:
string s = "world" ;
string u = "hello" + s;
// 上面语句等价于 "hello".operator+(s) ,显然是错误的