C++知识总结——运算符重载
3.运算符重载
3.1运算符重载概念
C++中预定义的运算符的操作对象只能是基本数据类型。但实际上,对于许多用户自定义类型(例如类),也需要类似的运算操作。这时就必须在C++中重新定义这些运算符,赋予已有运算符新的功能,使它能够用于特定类型执行特定的操作。运算符重载的实质是函数重载或函数多态。
运算符重载函数定义:
<返回类型说明符> operator <运算符符号>(<参数表>)
{
<函数体>
}
3.2运算符重载规则
- 重载的运算符必须至少有一个操作数是用户定义的类型,防止用户给标准运算符重载。也就是禁止给标准“+”,“-”,“*”,“/”等进行重载,防止出现二义性。
- 使用运算符不能违反运算符原来的句法规则。例如不能将%求模运算重载成操作数。
- 不能创建新的运算符。
- 不能修改运算符原先的优先级。
- 不能重载的运算符:
成员运算符,作用域解析运算符,条件运算符,sizeof运算符,typeid(一个RTTI运算符),const_cast、dynamic_cast、reinterpret_cast、static_cast强制类型转换运算符
- 大多数运算符可以通过成员函数和非成员函数进行重载但是下面这四种运算符只能通过成员函数进行重载:
= 赋值运算符,()函数调用运算符,[ ]下标运算符,->通过指针访问类成员的运算符。
3.3运算符重载形式
运算符函数重载一般有两种形式:重载为类的成员函数和重载为类的非成员函数。非成员函数通常是友元。(可以把一个运算符作为一个非成员、非友元函数重载。但是,这样的运算符函数访问类的私有和保护成员时,必须使用类的公有接口中提供的设置数据和读取数据的函数,调用这些函数时会降低性能。可以内联这些函数以提高性能。)
-
重载为成员函数
当运算符重载为类的成员函数时,函数的参数个数比原来的操作数要少一个(后置单目运算符除外),这是因为成员函数用this指针隐式地访问了类的一个对象,它充当了运算符函数最左边的操作数。因此:
(1)双目运算符重载为类的成员函数时,函数只显式说明一个参数,该形参是运算符的右操作数。
(2)前置单目运算符重载为类的成员函数时,不需要显式说明参数,即函数没有形参。
(3)后置单目运算符重载为类的成员函数时,函数要带有一个整型形参。 -
重载为非成员函数(友元函数)
当运算符重载为类的友元函数时,由于没有隐含的this指针,因此操作数的个数没有变化,所有的操作数都必须通过函数的形参进行传递,函数的参数与操作数自左至右一一对应。 -
两种重载形式的比较
在多数情况下,将运算符重载为类的成员函数和类的友元函数都是可以的。但成员函数运算符与友元函数运算符也具有各自的一些特点:
(1)一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。
(2)以下一些双目运算符不能重载为类的友元函数:=、()、[]、->。
(3)类型转换函数只能定义为一个类的成员函数而不能定义为类的友元函数。
(4)若一个运算符的操作需要修改对象的状态,选择重载为成员函数较好。
(5)若运算符所需的操作数(尤其是第一个操作数)希望有隐式类型转换,则只能选用友元函数。
(6)当运算符函数是一个成员函数时,最左边的操作数(或者只有最左边的操作数)必须是运算符类的一个类对象(或者是对该类对象的引用)。如果左边的操作数必须是一个不同类的对象,或者是一个内部类型的对象,该运算符函数必须作为一个友元函数来实现。
(7)当需要重载运算符具有可交换性时,选择重载为友元函数。