运算符重载

来源:互联网 发布:linux ping脚本 编辑:程序博客网 时间:2024/05/29 18:36

运算符重载:

运算符是一种特殊的函数:操作数是函数的参数,运算结果是函数的返回值。

运算符重载不会改变内置类型表达式中运算符含义,只有至少一个操作数是用户自定义类型的对象时,才有可能调用该类中重载的运算符。

运算符函数

运算符函数的参数个数取决于两个因素。

(1)运算符的操作数个数:是一元运算符还是二元运算符。

(2)运算符函数是成员函数还是全局函数。

将运算符定义为成员函数时,因为调用成员函数的对象(this指向的对象)被作为运算符的第一个操作数,所以对一元运算符函数无须再提供参数。使用成员函数重载二元运算符时,将当前对象(this指向的对象)作为左操作数,只需要提供一个参数作为右操作数

如果将运算符函数定义为全局函数,由于进行运算时往往要访问类的私有数据,所以一般将其声明为类的友元。重载一元运算符时需要提供一个类类型的参数,重载二元运算符时需要提供两个参数,分别作为左、右操作数,其中至少一个参数必须是类类型的

 

运算符重载的限制:

Ø  只有C++预定义运算符集合中的运算符才可以重载,下表列出了可以重载的运算符。

Ø  C++中有些运算符不能被重载:作用域解析符(::)、成员选择符(.)、成员指针间接引用符(.*)和条件运算符(?:)。

Ø  不能定义C++中没有的运算符。例如,重载“operator**”会产生编译错误。

Ø  内置类型的运算符中预定含义不能改变,也不能为内置类型数据类型定义其他运算符。例如,不能定义内置数组的operator+。

Ø  重载运算符不能改变运算符的优先级和结合性。

Ø  重载运算符不能改变操作数的个数。

类别

运算符

一元运算符

+ - & * ++ ——

算数运算符

+ - * / %

关系运算符

== != < <= > >=

逻辑运算符

&& ||

位运算符

& | ^ ~ >> <<

赋值运算符

= += -= *= /= %= &= ^= |= >>= <<=

其他运算符

[] () -> ->* , new  delete

 

只有当用户自定义类型上的操作与内置运算符之间存在逻辑上的对应关系时,重载运算符才能使程序显得更自然、更直观。

 

自增和自减运算符 

自增和自减运算符都有前缀和后缀形式,因为都会改变对象,所以不能对常量对象操作。前缀形式返回改变后的对象,在成员运算符函数中返回*this。在全局运算符函数中返回修改后的参数。后缀形式返回改变之前的值,可以创建一个代表这个值的独立对象并返回它,因此,后缀运算是通过传值方式返回的。

后缀形式的自增和自减比前缀形式多一个int参数,这个参数在函数中并不使用只是作为重载函数的标记来区分前缀和后缀运算。例如,对Byte类对象b,b编译器看到++b会调用Byte::operator++(),而b++会调用Byte::operator++(int)。

如果要重载自增和自减运算符,一般应同时定义前缀和后缀形式。重载自增、自减运算符的行为应尽量与内置自增、自减保持一致,前缀形式返回被增量或减量对象引用,后缀形式则返回旧值。

 

运算符函数的参数和返回类型

(1)对于类类型的参数,如果仅仅只是读参数的值,而不改变参数,应该作为const引用来传递,因为普通算术运算符、关系运算符、逻辑运算符都不会改变参数,所以以const引用作为参数传递方式。当运算符函数是类的成员函数时,就将其定义为const成员函数。

(2)返回值的类型取决于运算符的具体含义。如果使用运算符的结果是产生一个新值,就需要产生一个作为返回值的新对象,通过传值方式返回,通常由const限定。如果函数返回的是操作数对象,则通常以引用方式返回,根据是否希望对返回的对象进行操作来决定是否返回const引用。

(3)所有赋值运算符均改变左值。为了使赋值结果能用于链式表达式,如a=b=c, 应该返回一个改变了左值的引用。一般赋值运算符的返回值是非const引用,以便能够对刚刚赋值的对象进行运算。

(4)逻辑运算符和关系运算符最好返回bool值,也可以返回int值或者typedef定义的等价类型。

 

全局运算符和成员运算符

成员运算符的限制是左操作数必须是当前类的对象,左操作数不能进行自动类型转换,而全局运算符为两个操作数都提供了转换的可能性。因此,如果左操作数是其他类的对象,或是希望运算符的两个操作数都能进行类型转换,则使用全局函数重载运算符。类似的情况还出现在为I/O 流重载运算符operator<< 及operator>>中。

原创粉丝点击