前言:
C++中预定义的运算符的操作对象只能是基本的数据类型。但实际上,对于许多用户自定义类型,也需要类似的运算符。这时就必须在C++中重新定义这些运算符,赋予已有运算符新的功能,使它能够用于特定类型执行特定操作。
定义:
使同一个运算符作用于不同类型数据时导致不同的行为的这种机制称为运算符重载。其重载是通过运算符函数实现的,其重载实质是函数重载。
C++编译器在对运算符进行编译处理时,将一个运算符编译成以下形式:
一元运算符:@obj——>operator @(obj)
二元运算符:obj1@obj2——>operator @ (obj1,obj2)
关键字operator加上运算符名的函数称为运算符函数。
形式:
重载为类的成员函数、重载为类的非成员函数(友元)。
优点:
在完成同样的操作时,使用运算符重载能够比一般的函数调用更简洁、更直观,增加程序可读性。
重载规则:
1)可重载的运算符
C++中的运算符除以下五个元算符之外,其余全部可以被重载。
. 成员选择元算符;
.* 成员指针元算符 ;
:: 作用域分辨符;
?: 三目选择运算符;
sizeof 计算数据大小运算符 。
2)重载规则:
a.重载后运算符的优先级和结合性不会改变。
b.不能改变原运算符操作数的个数。
c.不能重载C++中没有的运算符。
d.不能改变运算符的原有语义。
重载为类的友元函数:
目的:
运算符之所以重载为类的友元函数,是因为这样可以自由地访问该类的任何数据成员。
格式:
在类中定义友元函数的格式:
friend 函数类型 operator 运算符(形参表)
{
函数体;
}
注:
友元函数也可以在类中声明,在类外定义。由于友元函数不是类的成员函数,在类外定义时不需要加上类名标识。
重载为类的成员函数:
目的(好处):
这样运算函数可以自由地访问本类的数据成员。
格式:
返回类型 类名::operator 元算符(形参表)
{
函数体;
}
注:
1)类名是要重载该运算符的类,如果在类中定义运算符函数,类名与作用域分辨符可以省略。
2)operator与运算符构成运算符函数名。
3)当运算符重载为类的成员函数时,函数的参数个数将比原来的操作数个数少一个。
说明:
a.双目运算符重载为类的成员函数时,函数只显示一个参数,该参数是运算符的右操作数。
b.前置单目运算符重载为类的成员函数时,不需要显式说明参数,即函数 没有形参。
c.后置单目运算符重载为类的成员函数时,为了与前置单目运算符区别,函数要带有一个整型形参。
两种重载形式的比较:
1)一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。
2)一些 双目运算符不能重载为类的友元函数:=、()、[ ]、—>。
3)类型转换函数只能定义为一个类的成员函数而不能定义为类的友元函数。
4)若运算符的操作数需要修改对象的状态,选择重载为成员函数较好。
5)若运算符所需的操作数(尤其第一个)希望有隐式类型转换,则只能选用友元函数。
6)当运算符函数是一个成员函数时,最左边的操作数(或只有最左边的操作数)必须是运算符类的一个对象(或是该类对象的引用)。如果最左边的操作数必须是一个不同类的对象,或者是一个基本数据类型的对象,该运算符函数必须作为一个友元函数来实现。
7)当需要重载运算符的运算具有可交换性时,选择重载为友元函数。