1、类成员?全局函数?
(1)类成员:
a、二元运算符的参数只有一个,一元运算符不需要参数。之所以少一个参数,是因为这个参数是隐含的
b、指针操作符“->”、下标操作符“[]”、函数调用操作符“()”和赋值操作符“=”只能以成员函数的形式重载
(2)全局函数:
a、二元操作符需要两个参数,一元操作符需要一个参数。不管如何,必须要有一个参数是类类型对象(防止重载内置类型操作);
b、若左操作数是非类类型,则必须声明为全局函数;
c、一般情况下,重载运算符函数要用到 类的私有变量,所以我们将该函数声明为该类的友元函数
2、返回引用?直接返回?
要确定它的返回值是左值,还是右值。如果是左值最返回引用,如果是右值那就直接返回值。
3、自增运算符重载
后增(a++):整数形参,值返回
T operator++(int)
前增(++a):没有形参,引用返回
T& operator++()
4、类型转换
(1)
类型转换构造函数可以完成其它类型到类类型的转化,重载类型转换可以完成从类对象到其他类型的转换
注意:没有参数,没有显示标出返回类型(类型名就表示了返回类型),函数内只能返回要转换的类型对象
class X
{
public:
operator TYPE()
{
//.....
return TYPE对象;
}
};
(2)
一般来说,转换运算符与转换构造函数(即带一个参数的构造函数)是互逆的,如有了构造函数Test(int),那么最好有一个转换运算符int()。
这样就不必提供对象参数重载运算符了,如
Test a1(1);
Test a2(2);
Test a3;
a3 = a1+a2;
就不需要重载+号操作符了。
因为对于a1+a2的运算,系统可能会先找有没有定义针对Test的+号操作符,如果没有,它就会找有没有针对Test类转换函数参数类型的+号操作符
(因为可以将+号运行结果的类型通过转换函数转换为Test对象),因为Test类有个int类型的参数,对于int类型有+操作符,所以a1+a2真正执行的是
Test(int(a1) + int(a2));即Test(3)
(3)
对于转换运算符,还有一个需要注意的地方就是,如果A类中有以B为参数的转换函数(构造函数),那B中不能有A的转换运算符,不然就存在转换的二义性,如:
class A
{
A(B&){…}
};
class B
{
operator A(){…}
};
// 那么以下语句就会有问题:
B b;
A(b); //A(b)有就可能是A的构造函数,也可以是B的转换运算符
5、令operator= 返回一个 reference to *this
正如可以进行如下的操作
int x, y, z;
x = y = z = 2;
赋值采用右结合律,上式会被编译器解析为:
x = ( y = ( z = 2 ) );
相当于2首先赋值给z,然后整个表达式(z = 2)返回 z,再把 y 赋值为 z。
所以,为了同样实现连锁赋值,赋值操作符应当返回一个 reference 指向操作符的左侧实参。如下所示:
class A {
public:
A& operator=(const A& rhs) {
...
return *this;
}
};
当然,该协议同样适用于所有赋值相关的运算,如:
T& operator+=(const T& rhs);
T& operator-=(const T& rhs);
函数最后都应当返回一个指向该操作符左参数的引用:
return *this;