运算符重载就是允许由程序员重新定义,这一机制称为运算符重载。
运算符重载的方式:定义一个重载运算符的函数,当执行到呗重载的运算符时,系统自动调用该函数,以实现向应得运算。
运算符重载是通过定义函数实现的,运算符重载实质上是函数的重载。
运算符重载函数分为一下两种形式:
(1)类成员函数;
(2)普通函数;——通过声明为“类的友元函数”操作类成员
类成员运算符重载的一般形式:
函数类型 类名::operator运算符符号(参数表){
……//运算符函数体
}
尽管运算符函数的返回值类型可以是任意的,但,通常设计为当前的类类型以便进行复合运算,有需要时也会设计为当前类型的引用,以兼顾复合运算符及修改左值。
operator=()函数的返回值类型为complex(左图);
1.当operator=()的返回值类型为普通类类型,则会在operator()调用结束时有掉用copy构造函数生成临时无名对象存放函数返回值,无名对象为const对象。
operator=()函数返回类型为complex&(右图):
1.调用operator=()时,不会在函数调用结束时调用copy构造函数产生临时无名对象。除此以外,与函数返回类型为complex无差异。
1.operator=()的返回值为类类型(不带&),执行结果与c1=c2=c3;相同。
2.当operator=()的返回值类型为普通类类型,即函数调用结束时又调用了copy构造函数生成无名临时变量存放函数返回值,即:先后两次copy构造函数的调用,分别由从c1=(c2=c3);先后两次调用operator=()所导致。
operator=()函数的返回类型为complex&(右图):
1.每次调用operator=()时,不会在函数调用结束时产生临时无名对象,因此不会调用copy构造函数。执行结果与c1=c2=c3;相同
“类内”重载
(1)为什么一些二目运算符我们只设计了一个参数?因为我们多这些运算符是进行类内重载,其实这些二目运算符都有两个参数,另一个缺省参数的规定为this。
result.real=real + right.real;
相当于
result.real=this->real + right.real;
c1+c2 相当于 c1.operator+(c2);
(2)运算符重载的目的在于扩大运算符的功能,并且保留之前的功能
类外重载
运算符重载的规则
1)运算符=(赋值运算符)、[](下标运算符)、()(函数调用运算符)、->(通过指针访问类成员的运算符)必须定义为类的成员函数,不能定义为友元或普通函数;
运算符<<(输出流)、>>{流输入)则必须定义到类外,不能定义为类的成员函数。
2)不能创建新的运算符,只能对已有的1运算符进行重载。
3)运算符中绝大部分的运算符允许重载。不能重载的运算符只有五个:
. *(成员访问指针运算符)
.(成员访问运算符)
::(域运算符)
sizeof(长度运算符)
?:条件运算符
1)前两个不能重载是为了保护访问成员的功能不能被改变
2)第三个和第四个的运算对象是类型,而不是变量或一半表达式,不具有重载特征。
4)重载不能改变运算符个数。
5)重载不能改变运算符的优先级别与结合性。
6)重载的运算符函数不能有默认参数,否则就改变了参数的个数,与4)矛盾。
7)重载运算符必须和用户自定义类型的对象一起使用,其参数至少应该有一个是类对象
8)用于类对象的运算符一般必须重载,但运算符=和&不必用户重载。
(1)赋值运算符=可以用于每一个类对象,可以利用它在同类对象之间相互赋值。
(2)地址预算符&也不必重载,它能返回类对象在内存空间中的起始地址
9)应当是重载运算符的功能,类似于该运算符作用于标准乐星数据时所实现的功能,支持型惯性思维。
10)运算符重载可以是类的成员函数,也可以是类的友元函数,还可以是既非类的成员函数也不是友元函数的普通函数。