4运算符重载概要

上传人:今*** 文档编号:108060245 上传时间:2019-10-22 格式:PPT 页数:64 大小:754KB
返回 下载 相关 举报
4运算符重载概要_第1页
第1页 / 共64页
4运算符重载概要_第2页
第2页 / 共64页
4运算符重载概要_第3页
第3页 / 共64页
4运算符重载概要_第4页
第4页 / 共64页
4运算符重载概要_第5页
第5页 / 共64页
点击查看更多>>
资源描述

《4运算符重载概要》由会员分享,可在线阅读,更多相关《4运算符重载概要(64页珍藏版)》请在金锄头文库上搜索。

1、第 4 章:运算符重载,引言,运算符和函数,4=1 + 3,4.0=1.0 + 3.0,函数名,参数int,返回值int,函数名,参数double,返回值double,int + (int, int );,double + (double, double );,可以将+代表的操作看成一个函数:+为函数的名字,+操作的两个操作数的类型即为函数形参的类型,+操作的结果的类型即为函数的返回值类型。,C/C+中,每种基本数据类型的变量都可通过几种运算符来做相关计算,如int型变量,它们可以同“+”,“-”,“*”,“/”等运算符来做加法,减法,乘法,除法等。如:,int a, b; a+b; a-b;

2、 a*b; a/b;,class Vector int * data; int num; public: ,我们能否将自定义的类的对象也通过“+”,“-”,“*”,“/”等运算符来进行两个对象的加,减,乘,除呢?如:,Vector vec1,vec2 vec1+vec2; vec1-vec2; vec1*vec2; vec1/vec2;,定义一个向量类,两个向量类对象的加减乘除,C+提供了运算符重载机制来帮助我们实现上述目的。,运算符重载的提出,本 章 内 容,运算符重载的基本语法,运算符的使用和普通函数在语法上有所不同,但是可以将运算符看作是一种特殊的函数,操作数是函数的参数,运算结果是函数

3、的返回值。 其实在我们知道“运算符重载”的概念之前,已经在重载运算符了,例如: int a = 1 double d = 2.3; a + d; a + 1; d +1.5; 在C+ 中,为一个类类型定义运算符和普通函数的定义形式很相似,只是函数的名字是关键字operator后紧跟要重载的运算符。例如,重载的“+” 运算符函数名字为 operator+ 。定义了运算符函数之后,就可以对类类型的操作数使用该运算符。,(1) 运算符函数,定义重载运算符和定义普通函数类似,只是该函数的名字是opeartor ,表示要重载的运算符。 函数的参数个数取决于两个因素: 运算符的操作数个数: 一元运算符 二

4、元运算符 运算符函数: 成员函数 全局函数,将运算符函数定义为成员函数时,调用成员函数的对象(this指向的对象)被作为运算符的第一个操作数,所以如果是一元运算符,无需提供参数。使用成员函数重载二元运算符时,将当前对象(this指向的对象)作为左操作数,需要提供一个参数作为右操作数。 如果将运算符函数定义为全局函数,则通常要将其声明为类的友元函数。重载一元运算符时需要提供一个类类型的参数,重载二元运算符时需要提供两个参数,分别作为左右操作数,其中至少一个参数必须是类类型的。,#include class MinInt char b; public: MinInt(char ch = 0) :

5、b(ch) MinInt operator-( )const /一元运算“-“ cout“MinInt:operator-“endl; return MinInt(-b); MinInt operator+(const MinInt /end of class MinInt,int main() cout “内置数据类型:“ endl; int v1 = 1, v2 = 2, v3 = 3; v3 += v1 + v2; cout “用户自定义类型:“ endl; MinInt b1(10), b2(20), b3(30); b3 += -b1 + b2; /调用重载的运算符 程序的输出结果为

6、: 内置数据类型: 用户自定义类型: MinInt:operator- MinInt:operator+ MinInt:operator+=,(2) 运算符重载的限制,只有C+预定义运算符集合中的运算符才可以重载 C+中有些运算符不能被重载::(作用域解析符)、.(成员选择符)、.*(成员指针间接引用符)及?:(条件运算符)。 不能定义C+中没有的运算符,如operator*会产生编译错误。 内置类型的运算符的预定义意义不能改变,也不能为内置数据类型定义其他运算符。例如,不能定义内置数组的operator+。 重载运算符不能改变运算符的优先级和结合性。 重载运算符不能改变操作数的个数。,可以重

7、载的运算符,2 常用运算符的重载,本节给出一些常规运算符以成员函数和友元函数两种方式重载的例子。在下面的代码中,我们分别以两个类Integer和Byte 来举例说明如何使用成员函数和友元函数重载常用的运算符。,(1) 一元运算符,class Byte unsigned char b; public: Byte(unsigned char bb = 0) : b(bb) / 无副作用的运算符定义为 const成员函数 const Byte,一元运算符函数是成员函数时,形式参数列表里没有参数。,/ 有副作用的运算符定义为非const成员函数 const Byte,前缀形式返回改变后的对象,返回*t

8、his。,后缀形式返回改变之前的值,所以必须创建一个代表这个值的独立对象并返回它,是通过传值方式返回的。,int参数是用来区分前缀和后缀的;调用时系统传0;去掉就变成前缀形式,/ 重载运算符的使用示例 int main() Byte a, b, *bp; +b; -b; b; bp = /end of main(),用全局友元函数重载一元运算符,class Integer long i; Integer* This( ) return this; public: Integer(long ll = 0) : i(ll) friend const Integer,/ 全局运算符函数的定义 con

9、st Integer ,const Integer ,/ 重载运算符的使用 int main( ) Integer a, * ip ; +a; -a; a; ip = /end of main,自增和自减运算符,自增和自减运算符有前缀和后缀两种形式,都会改变对象,所以不能对常量对象操作。 前缀形式返回改变后的对象,返回*this。 后缀形式返回改变之前的值,所以必须创建一个代表这个值的独立对象并返回它,是通过传值方式返回的。 如何区分前缀和后缀形式呢? 后缀形式的自增和自减比前缀形式多一个int参数,这个参数在函数中并不使用,只是作为重载函数的标记来区分前缀和后缀运算。例如,对Byte类对象b

10、,编译器看到+b,会调用Byte:opeartor+(), 而b+会调用Byte:operator+(int)。 如果要重载自增和自减运算符,一般应同时定义自增、自减运算符的前缀式和后缀式。重载运算符的行为应尽量与内置运算符保持一致。,(2) 二元运算符,用成员函数重载二元运算符 class Byte unsigned char b; public: Byte(unsigned char bb = 0) : b(bb) const Byte operator+(const Byte,/位运算符 , ,Byte ,/关系运算符有 =, !=, ,= bool operator=(const By

11、te /end of class Byte,用全局函数重载二元运算符,全局函数重载二元运算符时,要带两个参数,其中至少有一个是类类型的。 第一个参数作为左操作数;第二个参数是右操作数。 注意,赋值运算符operator= 只能用成员函数重载。,class Integer long i; public: Integer(long ll = 0) : i(ll) friend const Integer operator+(const Integer,/ 修改并返回左值的复合赋值运算符,第一个参数是非const引用,即左值 friend Integer,/算术运算符,只给出+和/的定义,其余实现方

12、式类似,略 const Integer operator+(const Integer ,/ 复合赋值运算符,此处只给出了+=, /=和 ,/ 关系运算符和逻辑运算符,此处给出了=和 ,(3) 运算符函数参数/返回类型,各种不同的参数传递和返回方法,选择要合 乎逻辑: 对于任何参数类型,如果仅仅只是读参数的值,而不改变参数,应该作为const引用来传递。普通算术运算符、关系运算符、逻辑运算符都不会改变参数,所以以const引用作为主要的参数传递方式。当运算符函数是类的成员函数时,就将其定义为const成员函数。 返回值的类型取决于运算符的具体含义。如果使用运算符的结果是产生一个新值,就需要产生

13、一个作为返回值的新对象,这个对象作为一个常量通过传值方式返回。如果函数返回的是原有对象,则通常以引用方式返回,根据是否希望对返回的值进行运算来决定是否返回const引用。 所有赋值运算符均改变左值。为了使赋值结果能用于链式表达式,如a=b=c,应该返回一个改变了的左值的引用。一般赋值运算符的返回值是非const引用,以便能够对刚刚赋值的对象进行运算。 逻辑运算符和关系运算符最好返回bool值,也可返回int值或者由typedef定义的等价类型。,返回值优化,通过传值方式返回创建的新对象时,使用一种特殊的语法,例如在operator+中: return Integer(left.i + righ

14、t.i); 这种形式看起来像是一个构造函数的调用,这称为临时对象语法,含义是创建一个临时的Integer对象并返回它。 这种方式和创建一个有名字的对象并返回它是否相同呢?例如: Integer temp(left.i + right.i); return temp; 这两条语句先创建temp对象,会调用构造函数。然后拷贝构造函数把temp拷贝到外部返回值的存储单元,最后在temp作用域的结尾时调用析构函数。 返回临时对象的方式不同与此。当编译器看到这种语法时,会明白创建这个对象的目的只是返回它,所以编译器直接把这个对象创建在外部返回值的存储单元中,所以只需要调用一次构造函数,不需要拷贝构造函数

15、和析构函数的调用。因此,使用临时对象语法的效率非常高,这被称为返回值优化。,(4) 全局运算符和成员运算符,大部分运算符可以使用成员函数和全局函数两种方式重载。在这两种方式之间如何选择呢? 总的来说,如果没有什么差异,应该是成员运算符,因为这样强调了运算符和类的密切关系。但有时我们会因为另外一个原因选择使用全局函数重载运算符,如下例:,class Number int i; public: Number(int ii = 0) : i(ii) const Number operator+(const Number /左操作数转换为Number ,可以看到,使用成员运算符的限制是左操作数必须是当

16、前类的对象,左操作数不能进行自动类型转换,而全局运算符为两个操作数都提供了转换的可能性。因此,如果左操作数是其他类的对象,或是希望运算符的两个操作数都能进行类型转换,则使用全局函数重载运算符。 类似的情况还出现在为 I/O流重载运算符 operator时。,(5) 重载输入/输出运算符,operator 带两个操作数,左操作数cin是istream 类型的对象,而右操作数是接收输入数据的变量。输入操作会引起两个操作数的改变,因而,这两个参数需要传递非const引用。 operator 可以用于链式表达式,如 cinbc。这等价于: cinb; cinc; 由此看到这个运算应该返回istream对象cin本身,并且可以继续用于输入。 重载operator的基本形式如下: istream,重载operator,#include class

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号