《运算符重载》PPT课件.ppt

上传人:sh****n 文档编号:13178204 上传时间:2020-06-06 格式:PPT 页数:81 大小:455.50KB
返回 下载 相关 举报
《运算符重载》PPT课件.ppt_第1页
第1页 / 共81页
《运算符重载》PPT课件.ppt_第2页
第2页 / 共81页
《运算符重载》PPT课件.ppt_第3页
第3页 / 共81页
点击查看更多>>
资源描述
第四章运算符重载,4.1什么是运算符重载4.2运算符重载的方法4.3重载运算符的规则4.4运算符重载函数作为类成员函数和友元函数4.5重载双目运算符4.6重载单目运算符4.7重载流插入运算符和流提取运算符4.8不同类型数据间的转换,4.1什么是运算符重载,C+为程序员提供了灵活的手段,让程序员自己定义类,自己设计相应的运算符(必须在已有的运算符基础上设计),使之应用于自己定义的类。与函数重载类似,对已有的运算符赋予新的含义,用一个运算符表示不同功能的运算,这就是运算符重载。实际上,我们在此之前已经使用了运算符重载。如是C+的移位运算符,它又与流对象cout配合作为流插入运算符,这是C+对imag+c2.imag;在main函数中通过对象c1调用加法函数,上面的语句相当于:c.real=c1.real+c2.real;c.imag=c1.imag+c2.imag;能否用+运算符实现复数加法?,4.2运算符重载的方法,运算符重载的方法是定义一个重载运算符函数,在需要时系统自动调用该函数,完成相应的运算。运算符重载实质上是函数的重载。运算符重载函数的格式是:数据类型operator运算符(形参表)重载处理数据类型:是重载函数值的数据类型。operator是保留字,规则和限制,C+中可以重载除下列运算符外的所有运算符:.*:?:sizeof()只能重载C+语言中已有的运算符,不可臆造新的。不改变原运算符的优先级和结合性。不能改变操作数个数。经重载的运算符,其操作数中至少应该有一个是自定义类型。,两种形式,重载为类成员函数。重载为友元函数。,运算符函数,声明形式函数类型operator运算符(形参).重载为类成员函数时参数个数=原操作数个数-1(后置+、-除外)重载为友元函数时参数个数=原操作数个数,且至少应该有一个自定义类型的形参。,不能重载的运算符只有5个:.成员运算符.*成员指针运算符:域运算符sizeof长度运算符?:条件运算符重载函数名是由operator和运算符联合组成。复数加法运算符重载函数原型可以是:Complexoperator+(Complex例4.2重载运算符+,用于两个复数相加。,分析:定义一个复数类,用成员函数实现加号的重载函数。两个复数相加结果仍是复数,所以函数的返回值的类型也是复数类。用成员函数实现运算符重载函数时,调用格式是“对象名.成员名”,此时对象就是一个参与运算的操作数,加法还需要另一个操作数,这个操作数用函数的参数传递,参数的类型就是复数类。而运算结果用函数值返回。,classComplexpublic:Complex()real=0;imag=0;Complex(doubler,doublei)real=r;imag=i;Complexoperator+(Complex,ComplexComplex:operator+(Complex,intmain()Complexc1(3,4),c2(5,-10),c3;c3=c1+c2;coutc1=;c1.display();coutc2=;c2.display();coutc1+c2=;c3.display();return0;,说明:(1)用运算符重载函数取代了例4.1中的加法成员函数,从外观上看函数体和函数返回值都是相同的。(2)在主函数中的表达式c3=c2+c1取代了例4.1中的c3=plex_add(c2),编译系统将表达式c3=c1+c2解释为c1.operator+(c2)对象c1调用的重载函数operator+,以c2为实参计算两个复数之和。,请考虑在例4.2中能否用一个常量和一个复数相加?如c3=3+c2;/错误应该定义对象:ComplexC1(3.0,0):c3=C1+c2;注意:运算符重载后,其原来的功能仍然保留,编译系统根据运算表达式的上下文决定是否调用运算符重载函数。运算符重载和类结合起来,可以在C+中定义使用方便的新数据类型。,4.3重载运算符的规则,(1)C+只允许已有的部分运算符实施重载。(2)不能重载的运算符有五个。(3)重载不改变操作数的个数。(4)重载不改变运算符的优先级。(5)运算符重载函数不能带默认值参数。(6)运算符重载函数必须与自定义类型的对象联合使用,其参数至少有一个类对象或类对象引用。(7)C+默认提供=和imag=0;Complex(doubler)real=r;imag=0;Complex(doubler,doublei)real=r;imag=i;friendComplexoperator+(Complex,Complexoperator+(Complex,intmain()Complexc1(3,4),c2(5,-10),c3;c3=c1+c2;coutc1=;c1.display();coutc2=;c2.display();coutc1+c2=;c3.display();return0;,加法运算符重载为友元函数,C+在编译时将表达式c1+c2解释为operator+(c1,c2)即相当于执行以下函数Complexoperator+(Complex因为普通函数是不能直接访问对象的私有成员,如果普通函数必须访问对象的私有成员,可调用类的公有成员函数访问对象的私有成员。这会降低效率。,书上的错误,如想将一个复数和一个整数相加,运算符重载函数作为成员函数定义如下:ComplexComplex:operator+(int注意在运算符+的左侧必须是Complex类对象,程序中可以写成:c3=c2+n不能写成:c3=n+c2,书上的错误,如果要求在使用重载运算符时,运算符左侧操作数不是对象,就不能使用前面定义的运算符重载函数,可以将运算符重载函数定义为友元函数:friendComplexoperator+(int友元函数不要求第一个参数必须是类类型,但是要求实参要与形参一一对应:c3=n+c2/顺序正确c3=c2+n/顺序错误,为了实现加法的交换率,必须定义两个运算符重载函数,记住成员函数要求运算符左侧的操作数必须是自定义类型的对象,而友元函数没有这个限制,可以用下面两个组合中任意一个:(1)成员函数(左操作数是对象,右操作数是非对象)、友元函数(左操作数是非对象,右操作数是对象)(2)友元函数(左操作数是对象,右操作数是非对象)、友元函数(左操作数是非对象,右操作数是对象),由于使用友元会破坏类的封装,要尽量将运算符重载函数定义为成员函数。但考虑到各方面的因素,一般将单目运算符重载为成员函数,将双目运算符重载为友元函数。VC+6.0的不带后缀h的头文件不支持把成员函数重载为友元函数。但VC+6.0带后缀h的头文件支持这项功能,所以要将程序中的语句:#includeusingnamespacestd;改成:#include即可正常运行。,4.5重载双目运算符,双目的意思是运算符左边和右边的操作数均参加运算。如果要重载B为类成员函数,使之能够实现表达式oprd1Boprd2,其中oprd1为A类对象,则B应被重载为A类的成员函数,形参类型应该是oprd2所属的类型。经重载后,表达式oprd1Boprd2相当于oprd1.operatorB(oprd2)。,例4.4定义一个字符串类String,用来处理不定长的字符串,重载相等、大于、小于关系运算符,用于两个字符串的等于、大于、小于的比较运算。操作数:两个操作数都是字符串类的对象。规则:两个字符串进行比较。将“”运算重载为字符串类的成员函数。,(1)先建立一个String类#include#includeclassString/String是用户自己指定的类名public:String()p=NULL;String(char*str);voiddisplay();private:char*p;,String:String(char*str)p=str;voidString:display()coutp;intmain()Stringstring1(Hello),string2(Book);string1.display();cout(String,String:String(char*str)p=str;voidString:display()cout(String,booloperator(String,intmain()Stringstring1(Hello),string2(Book),string3(Computer);coutstring2)endl;cout(string1string3)endl;cout(string1=string2)endl;return0;运行结果为100,4.6重载单目运算符,单目运行符只要一个操作数,由于只有一个操作数,重载函数最多只有一个参数,如果将运算符重载函数定义为成员函数还可以不用参数。下面以自增运算符+为例,学习单目运算符的重载函数的编写方法。例4.5有一个Time类,数据成员有时、分、秒。要求模拟秒表,每次走一秒,满60秒进位,秒又从零开始计数。满60分进位,分又从零开始计数。输出时、分和秒的值。,#includeusingnamespacestd;classTimepublic:Time()hour=0;minute=0;sec=0;Time(inth,intm,ints):hour(h),minute(m),sec(s)Timeoperator+();voiddisplay()couthour:minute:sec=60)minute=minute-60;hour+;hour=hour%24;return*this;,43,intmain()Timetime1(23,59,0);for(inti=0;i61;i+)+time1;time1.display();return0;,C+中除了有前+外,还有后+。同样的运算符由于操作数的位置不同,含义也不同。怎样区分前+和后+?C+给了一个方法,在自增或自减运算符重载函数中,增加一个int形参。程序员可以选择带int形参的函数做后+,也可以选择不带int形参的函数做前+。例4.6在例4.5的基础上增加后+运算符重载函数。,#includeusingnamespacestd;classTimepublic:Time()hour=0;minute=0;sec=0;Time(inth,intm,ints):hour(h),minute(m),sec(s)Timeoperator+();Timeoperator+(int);voiddisplay()couthour:minute:sec=60)minute=minute-60;hour+;hour=hour%24;return*this;,47,分析:后+运算的含义是操作数先参加其他运算后再自加。如m=n+先将n的值赋予m,然后n再自加1。设计后+重载函数要遵循这个特性。TimeTime:operator+(int)Timetemp(*this);/保存修改前的对象做返回值+(*this);returntemp;,intmain()Timetime1(21,34,59),time2;couttime1:;time1.display();+time1;cout+time1:;time1.display();time2=time1+;couttime1+:;time1.display();cout和usingnamespacestd;把头文件包含到程序中。用户自定义类型的数据不能直接用输出和输入,如想用它们进行输入或输出,程序员必须对它们重载。,重载函数原型的格式如下:istream从格式上看,重载函数和重载函数只能定义为友元函数,不能定义为成员函数,因为函数有两个形参,并且第一个形参不是自定义类型。,4.7.1重载流插入运算符“”,例4.7在例4.2的基础上用重载函数输出复数。分析:在类中声明重载函数是友元函数friendostream,/本程序适用于VC+6.0#includeintmain()Complexc1(2,4),c2(6,10),c3;c3=c1+c2;coutc3;return0;,分析C+怎样处理”coutc3;”语句运算符的左边是ostream的对象cout,右边是程序员自定义类complex的对象c3,语句符合运算符重载友元函数operator的形参类型要求,系统调用友元函数,C+把这个语句解释为:operator(cout,c3);通过形参引用传递,函数中的output就是cout,函数中的c就是c3,函数就变成:cout(c3.real+c3.imagi)endl;returncout;,returncout是将输出流现状返回。C+规定运算符”,例4.8在例4.7的基础上增加流提取运算符重载函数,用cin输入复数,用cout(istream,intmain()Complexc1,c2;cinc1c2;cout重载函数中的形参input是istream类对象引用,在执行cinc1时,调用operator函数,将cin引用传递给input,input是cin的别名,同样c是c1的别名。因此,inputc.realc.imag;相当于cinc1.realc1.imag。函数返回cin的新值。使程序可以用重载函数连续从输入流提取数据给complex类对象。,程序逻辑上是正确的,但还有缺陷,如果输入的虚部是负数时,输出的形式变成:c2=(4+-10i)在负数前多个正号。可以对程序稍做修改:ostream,从本章例子中可以注意到,在运算符重载中使用引用参数的重要性,用引用形参在调用函数时,通过传递地址方式让形参成为实参的别名,不用生成临时变量,减少了时间和空间的开销。此外,如重载函数的返回值是对象引用时,返回的是对象,它可以出现在赋值号的左侧而成为左值,可以被赋值或参与其他操作(如保留cout流的当前值以便能连续使用输出)。,4.8.1标准类型数据间的转换,inti=6;i=7.5+i;编译过程:7.5作为double型数处理求解表达式时,将6转换陈double,然后再和7.5相加得到的13.5的值向整型变量i赋值时,先转换为13再赋值这种转换是c+编译系统自动完成的,称为隐式类型转换。,C+的显式类型转换,是一种人为的强制转换。格式:类型名(数据)例如:int(89.5)C语言中的采用形式(类型名)数据如:(int)89.5C+保留了c语言的用法,提倡用c+的方法,4.8.2用转换构造函数进行类型转换,作用:将一个其它类型的数据转换成一个指定的类的对象。转换构造函数只有一个形参,如Complex(doubler)real=r;imag=0;其作用就是将double型的参数r转换成Complex类的对象Complexc1(3.5);/建立一个对象,调用构造函数可以用声明语句建立一个无名的Complex对象,如Complex(3.6)/合法,但无法使用可以在一个表达式中使用无名对象,如c1=complex(3.6);/假设c1已被定义为Complex类的对象,转换构造函数也是一种构造函数,它遵循构造函数的一般规则。通常把有一个参数的构造函数用作类型转换,所以,称为转换构造函数。注意:转换构造函数只能有一个参数。如果有多个参数,就不是转换构造函数。原因是:如果有多个参数的话,究竟是把哪个参数转换成类的对象呢,使用转换构造函数将一个指定的数据转换成类的对象的方法如下:(1)先声明一个类(如上面的Complex)。(2)在这个类中定义一个只有一个参数的构造函数,参数的类型是需要转换的类型,在函数体中指定转换的方法。(3)在该类的作用域内可以用以下形式进行类型转换:类名(指定类型的数据),不仅可以将一个标准类型数据转换成类对象,也可以将另一个类的对象转换成转换构造函数所在类的对象。如:可以将一个学生类对象转换成教师类对象,可以在Teacher类中写出下面的构造函数:Teacher(Student注意:对象s中的num,name,sex必须是公有成员,否则不能被类外引用。,4.8.3用类型转换函数进行类型转换,作用:将一个类的对象转换成另一个类型的数据格式:operator类型名()实现转换的语句在函数名前面不能指定函数类型,函数没有参数返回值的类型是由函数名中指定的类型名来确定的。类型转换函数只能作为成员函数,因为转换的主体是本类的对象。不能作为友元函数或普通函数。,转换构造函数和类型转换运算符的共同功能:当需要的时候,编译系统会自动调用这些函数,建立一个无名的临时对象(或临时变量)例:doubled1,d2;Complexc1,c2;假设类中定义了类型转换函数对于表达式:d1=d2+c1;,编译系统发现“+”左侧的d2是double型,而右侧的c1是Complex类对象,如果没有对运算符“+”进行重载,就会检查有无类型转换函数,结果发现有对double的重载函数,就调用该函数,把Complex类对象c1转换为double型数据,建立一个临时的double变量,并与d2相加,最后将一个double型数据赋给d1。,如果类中已定义转换构造函数并重载了运算符“+”(作为Complex类的友元函数),但未对double定义类型转换函数(或者说未对double重载)对于表达式:c2=c1+d2;编译系统怎样处理呢?,它发现运算符“+”左侧的c1是Complex类对象,右侧的d2是double型。编译系统寻找有无对“+”的重载,发现有operator+函数,但它是Complex类的友元函数,要求两个Complex类的形参,即只能实现两个Complex类对象相加,而现在d2是double型,不合要求。在类中没有对double进行重载,因此不可能把c1转换为double型数据然后相加。编译系统就去找有无转换构造函数,发现有,就调用转换构造函数Complex(d2),建立一个临时的Complex类对象,在调用operator+函数,将两个复数相加,然后赋给c2。相当于执行表达式:c2=c1+Complex(d2),例4.9使用类型转换函数的简单例子#includeusingnamespacestd;classComplexpublic:Complex()real=0;imag=0;Complex(doubler,doublei)real=r;imag=i;operatordouble()returnreal;private:doublereal;doubleimag;intmain()Complexc1(3,4),c2(5,-10),c3;doubled;d=2.5+c1;coutdendl;return0;,5.5,分析:(1)如果在Complex类中没有定义类型转换函数operatordouble,程序编译将会出错。因为不能实现double数据类型与Complex类对象的相加。(2)如果在main函数中加一语句:c3=c2;编译系统是把c2按Complex类对象处理,因为赋值号两侧为同一类数据,可以合法赋值。(3)如果在Complex类中声明了重载运算符“+”函数作为友元函数,并在类外定义operator+函数:Complexoperator+(Complexc1,Complexc2)returnComplex(c1.real+c2.real,c1.imag+c2.imag);c3=c1+c2;/有运算符“+”重载,可以实现对象相加d=c1+c2;/先相加,再通过对double的重载函数将临时对象转化为double,再赋值,对类型的重载和对运算符的重载的概念和方法相似重载函数都使用关键字operator,它的意思是“运算符”。因此,通常把类型转换函数也成为类型转换运算符函数由于它也是重载函数,因此也称为类型转换运算符重载函数(或称强制类型转换运算符重载函数),例4.10包含转换构造函数、运算符重载函数和类型转换函数的程序#includeusingnamespacestd;classComplexpublic:Complex()real=0;imag=0;Complex(doubler)real=r;imag=0;Complex(doubler,doublei)real=r;imag=i;friendComplexoperator+(Complexc1,Complexc2);voiddisplay();private:doublereal;doubleimag;,Complexoperator+(Complexc1,Complexc2)returnComplex(c1.real+c2.real,c1.imag+c2.imag);voidComplex:display()cout(real+imagi)endl;,intmain()Complexc1(3,4),c2(5,-10),c3;c3=c1+2.5;c3.display();return0;,分析:(1)如果没有转换构造函数,则此程序编译出错,因为没有重载运算符使之能将Complex类对象与double数据相加。(2)由于重载了运算符“+”,表达式c1+2.5,编译系统解释为:operator+(c1,2.5)/2.5不是Complex类对象调用转换构造函数Complex(2.5),形成表达式:operator+(c1,Complex(2.5),(3)如果把“c3=c1+2.5”改为“c3=2.5+c1”。编译仍能通过。我们从中得到结论:在已定义了相应的转换构造函数情况下,将运算符“+”函数重载为友元函数,在进行两个复数相加时,可以使用交换律。如果运算符“+”重载函数不作为Complex类的友元函数,而作为Complex类的成员函数,不能满足交换律。函数的原型:operator+(Complexc2);/Complex类成员函数函数第一个参数省略了,它隐含指this所指的对象。对于表达式:c1+2.5c+编译系统解释为:c1.operator+(2.5),通过转换构造函数Complex(2.5),建立一个临时的Complex对象。则表达式相当于:c1.operator+(Complex(2.5).但对于表达式:2.5+c1。C+系统解释为(2.5).operator+(c1)/错误,如果运算符函数重载为成员函数,它的第一个参数必须是本类的对象。当第一个操作数不是类对象时,不能将运算符函数重载为成员函数。如果将运算符“+”函数重载为成员函数,交换律不适用。一般情况下,将双目运算符函数重载为友元函数。单目运算符则为重载成员函数。,(4)在上面的基础上增加类型转换函数:Complex类的公有部分为:public:Complex()real=0;imag=0;Complex(doubler)real=r;imag=0;Complex(doubler,doublei)real=r;imag=i;operatordouble()coutreturnreal;friendComplexoperator+(Complexc1,Complexc2);voiddisplay();,程序在编译时出错,原因是出现二义性。在处理c1+2.5时出现二义性。一种理解是:调用转换构造函数,把2.5变成Complex类对象,然后调用运算符“+”重载函数,与c1进行复数相加。另一种理解是:把c1转换成double型数,然后与2.5进行相加。系统无法判定,这两者是矛盾的。如果要使用类型转换函数,就应当删去运算符“+”重载函数。,
展开阅读全文
相关资源
相关搜索

当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!