谭浩强《C程序设计》课件第10章.ppt
《谭浩强《C程序设计》课件第10章.ppt》由会员分享,可在线阅读,更多相关《谭浩强《C程序设计》课件第10章.ppt(78页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第第10章章 运算符重载运算符重载10.1 什么是运算符重载什么是运算符重载10.2 运算符重载的方法运算符重载的方法10.3 重载运算符的规则重载运算符的规则10.4 运算符重载函数作为类成员函数和友元函数运算符重载函数作为类成员函数和友元函数10.5 重载双目运算符重载双目运算符10.6 重载单目运算符重载单目运算符10.7 重载流插入运算符和流提取运算符重载流插入运算符和流提取运算符10.8 不同类型数据间的转换不同类型数据间的转换所谓重载,就是重新赋予新的含义。函数重载就是对所谓重载,就是重新赋予新的含义。函数重载就是对一个已有的函数赋予新的含义,使之实现新功能。一个已有的函数赋予新的
2、含义,使之实现新功能。运算符也可以重载。实际上,我们已经在不知不觉之运算符也可以重载。实际上,我们已经在不知不觉之中使用了运算符重载。中使用了运算符重载。现在要讨论的问题是:现在要讨论的问题是:用户能否根据自己的需要对用户能否根据自己的需要对C+已提供的运算符进行重载,赋予它们新的含义,已提供的运算符进行重载,赋予它们新的含义,使之一名多用。譬如,能否用使之一名多用。譬如,能否用“+”号进行两个复数号进行两个复数的相加。在的相加。在C+中不能在程序中直接用运算符中不能在程序中直接用运算符“+”对复数进行相加运算。用户必须自己设法实现复数相对复数进行相加运算。用户必须自己设法实现复数相加。例如用
3、户可以通过定义一个专门的函数来实现复加。例如用户可以通过定义一个专门的函数来实现复数相加。见例数相加。见例10.1。10.1 什么是运算符重载什么是运算符重载例例10.1 通过函数来实现复数相加。通过函数来实现复数相加。#include using namespace std;class Complex /定义定义Complex类类public:Complex()real=0;imag=0;/定义构造函数定义构造函数Complex(double r,double i)real=r;imag=i;/构造函数重载构造函数重载Complex complex_add(Complex&c2);/声明复数
4、相加函数声明复数相加函数void display();/声明输出函数声明输出函数 private:double real;/实部实部double imag;/虚部虚部;Complex Complex complex_add(Complex&c2)Complex c;c.real=real+c2.real;c.imag=imag+c2.imag;return c;void Complex display()/定义输出函数定义输出函数cout(real,imagi)endl;int main()Complex c1(3,4),c2(5,-10),c3;/定义定义3个复数对象个复数对象c3=plex
5、_add(c2);/调用复数相加函数调用复数相加函数coutc1=;c1.display();/输出输出c1的值的值coutc2=;c2.display();/输出输出c2的值的值coutc1+c2=;c3.display();/输出输出c3的值的值return 0;运行结果如下:运行结果如下:c1=(3+4i)c2=(5-10i)c1+c2=(8,-6i)结果无疑是正确的,但调用方式不直观、太烦琐,使结果无疑是正确的,但调用方式不直观、太烦琐,使人感到很不方便。能否也和整数的加法运算一样,直人感到很不方便。能否也和整数的加法运算一样,直接用加号接用加号“+”来实现复数运算呢?如来实现复数运算
6、呢?如c3=c1+c2;编译系统就会自动完成编译系统就会自动完成c1和和c2两个复数相加的运算。两个复数相加的运算。如果能做到,就为对象的运算提供了很大的方便。这如果能做到,就为对象的运算提供了很大的方便。这就需要对运算符就需要对运算符“+”进行重载。进行重载。运算符重载的方法是定义一个重载运算符的函数,在运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。也就是说,运算符重载是通过定以实现相应的运算。也就是说,运算符重载是通过定义函数实现的。运算符重载实质上是函数的重载。义函数实现的。
7、运算符重载实质上是函数的重载。重载运算符的函数一般格式如下:重载运算符的函数一般格式如下:函数类型函数类型 operator 运算符名称运算符名称(形参表列形参表列)对运算符的重载处理对运算符的重载处理 例如,想将例如,想将“+”用于用于Complex类类(复数复数)的加法运算,的加法运算,函数的原型可以是这样的:函数的原型可以是这样的:Complex operator+(Complex&c1,Complex&c2);10.2 运算符重载的方法运算符重载的方法在定义了重载运算符的函数后,可以说:在定义了重载运算符的函数后,可以说:函数函数operator+重载了运算符重载了运算符+。为了说明在
8、运算符重载后,执行表达式就是调用函数为了说明在运算符重载后,执行表达式就是调用函数的过程,可以把两个整数相加也想像为调用下面的函的过程,可以把两个整数相加也想像为调用下面的函数:数:int operator+(int a,int b)return(a+b);如果有表达式如果有表达式5+8,就调用此函数,将,就调用此函数,将5和和8作为调用作为调用函数时的实参,函数的返回值为函数时的实参,函数的返回值为13。这就是用函数的。这就是用函数的方法理解运算符。方法理解运算符。可以在例可以在例10.1程序的基础上重载运算符程序的基础上重载运算符“+”,使之,使之用于复数相加。用于复数相加。例例10.2
9、改写例改写例10.1,重载运算符,重载运算符“+”,使之能用于,使之能用于两个复数相加。两个复数相加。#include using namespace std;class Complexpublic:Complex()real=0;imag=0;Complex(double r,double i)real=r;imag=i;Complex operator+(Complex&c2);/声明重载运算符的函数声明重载运算符的函数void display();private:double real;double imag;Complex Complex operator+(Complex&c2)/定
10、义重载运算符的函数定义重载运算符的函数 Complex c;c.real=real+c2.real;c.imag=imag+c2.imag;return c;void Complex display()cout(real,imagi)endl;int main()Complex c1(3,4),c2(5,-10),c3;c3=c1+c2;/运算符运算符+用于复数运算用于复数运算coutc1=;c1.display();coutc2=;c2.display();coutreal+c2.real,this-real就是就是c1.real。在在10.2节中已说明,在将运算符函数重载为成员函数节中已说
11、明,在将运算符函数重载为成员函数后,如果出现含该运算符的表达式,如后,如果出现含该运算符的表达式,如c1+c2,编译系编译系统把它解释为统把它解释为c1.operator+(c2)即通过对象即通过对象c1调用运算符重载函数,并以表达式中第调用运算符重载函数,并以表达式中第二个参数二个参数(运算符右侧的类对象运算符右侧的类对象c2)作为函数实参。运作为函数实参。运算符重载函数的返回值是算符重载函数的返回值是Complex类型,返回值是复类型,返回值是复数数c1和和c2之和之和(Complex(c1.real+c2.real,c1.imag+c2.imag)。运算符重载函数除了可以作为类的成员函数
12、外,还可运算符重载函数除了可以作为类的成员函数外,还可以是非成员函数。可以将例以是非成员函数。可以将例10.2改写为例改写为例10.3。例例10.3 将运算符将运算符“+”重载为适用于复数加法,重载函重载为适用于复数加法,重载函数不作为成员函数,而放在类外,作为数不作为成员函数,而放在类外,作为Complex类的类的友元函数。友元函数。#include using namespace std;class Complexpublic:Complex()real=0;imag=0;Complex(double r,double i)real=r;imag=i;friend Complex oper
13、ator+(Complex&c1,Complex&c2);/重载函数作为友元函数重载函数作为友元函数void display();private:double real;double imag;Complex operator+(Complex&c1,Complex&c2)/定义作为友元函数的重载定义作为友元函数的重载函数函数return Complex(c1.real+c2.real,c1.imag+c2.imag);void Complex display()cout(real,imagi)endl;int main()Complex c1(3,4),c2(5,-10),c3;c3=c1+
14、c2;coutc1=;c1.display();coutc2=;c2.display();coutc1+c2=;c3.display();与例与例10.2相比较,只作了一处改动,将运算符函数不相比较,只作了一处改动,将运算符函数不作为成员函数,而把它放在类外,在作为成员函数,而把它放在类外,在Complex类中声类中声明它为友元函数。同时将运算符函数改为有两个参数。明它为友元函数。同时将运算符函数改为有两个参数。在将运算符在将运算符“+”重载为非成员函数后,重载为非成员函数后,C+编译系编译系统将程序中的表达式统将程序中的表达式c1+c2解释为解释为operator+(c1,c2)即执行即执行
15、c1+c2相当于调用以下函数:相当于调用以下函数:Complex operator+(Complex&c1,Complex&c2)return Complex(c1.real+c2.real,c1.imag+c2.imag);求出两个复数之和。运行结果同例求出两个复数之和。运行结果同例10.2。为什么把运算符函数作为友元函数呢?因为运算符函为什么把运算符函数作为友元函数呢?因为运算符函数要访问数要访问Complex类对象中的成员。如果运算符函数类对象中的成员。如果运算符函数不是不是Complex类的友元函数,而是一个普通的函数,类的友元函数,而是一个普通的函数,它是没有权利访问它是没有权利访问
16、Complex类的私有成员的。类的私有成员的。在在10.2节中曾提到过:节中曾提到过:运算符重载函数可以是类的成运算符重载函数可以是类的成员函数,也可以是类的友元函数,还可以是既非类的员函数,也可以是类的友元函数,还可以是既非类的成员函数也不是友元函数的普通函数。现在分别讨论成员函数也不是友元函数的普通函数。现在分别讨论这这3种情况。种情况。首先,只有在极少的情况下才使用既不是类的成员函首先,只有在极少的情况下才使用既不是类的成员函数也不是友元函数的普通函数,原因是上面提到的,数也不是友元函数的普通函数,原因是上面提到的,普通函数不能直接访问类的私有成员。普通函数不能直接访问类的私有成员。在剩
17、下的两种方式中,什么时候应该用成员函数方式,在剩下的两种方式中,什么时候应该用成员函数方式,什么时候应该用友元函数方式?二者有何区别呢?如什么时候应该用友元函数方式?二者有何区别呢?如果将运算符重载函数作为成员函数,它可以通过果将运算符重载函数作为成员函数,它可以通过this指针自由地访问本类的数据成员,因此可以少写一个指针自由地访问本类的数据成员,因此可以少写一个函数的参数。但必须要求运算表达式第一个参数函数的参数。但必须要求运算表达式第一个参数(即即运算符左侧的操作数运算符左侧的操作数)是一个类对象,是一个类对象,而且与运算符函数的类型相同。因为必须通过类的对而且与运算符函数的类型相同。因
18、为必须通过类的对象去调用该类的成员函数,而且只有运算符重载函数象去调用该类的成员函数,而且只有运算符重载函数返回值与该对象同类型,运算结果才有意义。在例返回值与该对象同类型,运算结果才有意义。在例10.2中,表达式中,表达式c1+c2中第一个参数中第一个参数c1是是Complex类对类对象,运算符函数返回值的类型也是象,运算符函数返回值的类型也是Complex,这是正这是正确的。如果确的。如果c1不是不是Complex类,它就无法通过隐式类,它就无法通过隐式this指针访问指针访问Complex类的成员了。如果函数返回值类的成员了。如果函数返回值不是不是Complex类复数,显然这种运算是没有
19、实际意义类复数,显然这种运算是没有实际意义的。的。如想将一个复数和一个整数相加,如如想将一个复数和一个整数相加,如c1+i,可以将运可以将运算符重载函数作为成员函数,如下面的形式:算符重载函数作为成员函数,如下面的形式:Complex Complex operator+(int&i)/运算符重载函数作为运算符重载函数作为Complex类类的成员函数的成员函数return Complex(real+i,imag);注意在表达式中重载的运算符注意在表达式中重载的运算符“+”左侧应为左侧应为Complex类的对象,如类的对象,如c3=c2+i;不能写成不能写成c3=i+c2;/运算符运算符“+”的左
20、侧不是类对象,编译出错的左侧不是类对象,编译出错如果出于某种考虑,要求在使用重载运算符时运算符如果出于某种考虑,要求在使用重载运算符时运算符左侧的操作数是整型量(如表达式左侧的操作数是整型量(如表达式i+c2,运算符左侧运算符左侧的操作数的操作数i是整数),这时是无法利用前面定义的重是整数),这时是无法利用前面定义的重载运算符的,因为无法调用载运算符的,因为无法调用i.operator+函数。可想而函数。可想而知,如果运算符左侧的操作数属于知,如果运算符左侧的操作数属于C+标准类型标准类型(如如int)或是一个其他类的对象,则运算符重载函数不能或是一个其他类的对象,则运算符重载函数不能作为成员
21、函数,只能作为非成员函数。如果函数需要作为成员函数,只能作为非成员函数。如果函数需要访问类的私有成员,则必须声明为友元函数。可以在访问类的私有成员,则必须声明为友元函数。可以在Complex类中声明:类中声明:friend Complex operator+(int&i,Complex&c);/第一个参数可以不是第一个参数可以不是类对象类对象在类外定义友元函数:在类外定义友元函数:Complex operator+(int&i,Complex&c)/运算符重载函数不是成员运算符重载函数不是成员函数函数return Complex(i+c.real,c.imag);将双目运算符重载为友元函数时,
22、在函数的形参表列将双目运算符重载为友元函数时,在函数的形参表列中必须有两个参数,不能省略,形参的顺序任意,不中必须有两个参数,不能省略,形参的顺序任意,不要求第一个参数必须为类对象。但在使用运算符的表要求第一个参数必须为类对象。但在使用运算符的表达式中,要求运算符左侧的操作数与函数第一个参数达式中,要求运算符左侧的操作数与函数第一个参数对应,运算符右侧的操作数与函数的第二个参数对应。对应,运算符右侧的操作数与函数的第二个参数对应。如如c3=i+c2;/正确,类型匹配正确,类型匹配c3=c2+i;/错误,类型不匹配错误,类型不匹配请注意,数学上的交换律在此不适用。如果希望适用请注意,数学上的交换
23、律在此不适用。如果希望适用交换律,则应再重载一次运算符交换律,则应再重载一次运算符“+”。如。如Complex operator+(Complex&c,int&i)/此时第一个参数为类对象此时第一个参数为类对象return Complex(i+c.real,c.imag);这样,使用表达式这样,使用表达式i+c2和和c2+i都合法,编译系统会根都合法,编译系统会根据表达式的形式选择调用与之匹配的运算符重载函数。据表达式的形式选择调用与之匹配的运算符重载函数。可以将以上两个运算符重载函数都作为友元函数,也可以将以上两个运算符重载函数都作为友元函数,也可以将一个运算符重载函数可以将一个运算符重载函
24、数(运算符左侧为对象名的运算符左侧为对象名的)作为成员函数,另一个作为成员函数,另一个(运算符左侧不是对象名的运算符左侧不是对象名的)作作为友元函数。但不可能将两个都作为成员函数,原因为友元函数。但不可能将两个都作为成员函数,原因是显然的。是显然的。C+规定,有的运算符规定,有的运算符(如赋值运算符、下标运算符、如赋值运算符、下标运算符、函数调用运算符函数调用运算符)必须定义为类的成员函数,有的运必须定义为类的成员函数,有的运算符则不能定义为类的成员函数算符则不能定义为类的成员函数(如流插入如流插入“”、类型转换运算符、类型转换运算符)。由于友元的使用会破坏类的封装,因此从原则上说,由于友元的
25、使用会破坏类的封装,因此从原则上说,要尽量将运算符函数作为成员函数。但考虑到各方面要尽量将运算符函数作为成员函数。但考虑到各方面的因素,一般将单目运算符重载为成员函数,将双目的因素,一般将单目运算符重载为成员函数,将双目运算符重载为友元函数。在学习了本章第运算符重载为友元函数。在学习了本章第10.7节例节例10.9的讨论后,读者对此会有更深入的认识。的讨论后,读者对此会有更深入的认识。说明:说明:有的有的C+编译系统编译系统(如如Visual C+6.0)没有完没有完全实现全实现C+标准,它所提供不带后缀标准,它所提供不带后缀.h的头文件不支的头文件不支持把成员函数重载为友元函数。上面例持把成
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C程序设计 谭浩强 程序设计 课件 10
限制150内