c++-chap-10-运算符重载_第1页
c++-chap-10-运算符重载_第2页
c++-chap-10-运算符重载_第3页
c++-chap-10-运算符重载_第4页
c++-chap-10-运算符重载_第5页
已阅读5页,还剩61页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、课件作者:刘葳第第10章运算符重载章运算符重载10. 操作符重载的需要性操作符重载的需要性 C+语言本身没有提供复数类型,可定义一个类来实现:class Complex/复数类定义public: Complex(double r=0.0,double i=0.0) real=r; imag=i; void display() const cout real + imag i; . private: double real; double imag;如何实现两个复数(类型为Complex)相加?一种方案:为Complex类定义一个成员函数add,例如:class Complex public:C

2、omplex add(const Complex& x) constComplex temp;temp.real = real+x.real;temp.imag = imag+x.imag;return temp; ;Complex a(1.0,2.0),b(3.0,4.0),c;c = a.add(b);另一种方案:定义一个友元函数,例如:class Complex /复数类定义 . friendComplex complex_add(const Complex &x1, const Complex &x2); Complex complex_add(const Co

3、mplex &x1, const Complex &x2) Complex temp;temp.real = x1.real+x2.real;temp.imag = x1.imag+x2.imag;return temp;Complex a(1.0,2.0),b(3.0,4.0),c;c = complex_add(a,b);在前面的两种实现中,针对复数的加法操作,其形式不符合数学上的习惯:c=a+b,如何将其以数学的书写形式实现复数相加,这时就出现了运算符重载的概念 c+具备这一功能,可以解决这个问题1. 什么是运算符重载运算符重载的含义是:对已有的运算符进行重新定义,使它具

4、有新的功能,即就是用同一个运算符完成不同的运算操作。例如: 用用“+ +”运算符完成两个实数、两个复数运算符完成两个实数、两个复数、两个字符串的相关运算。、两个字符串的相关运算。61. 什么是运算符重载7实数实数 设:设:c1=10 c1=10 ,c2=20c2=20,则:,则:c1+c2=10+20=30c1+c2=10+20=30复数复数 设:设:c1=10+10ic1=10+10i,c2=20+20ic2=20+20i,则:,则:c1+c2=30+30i c1+c2=30+30i 字符串字符串 设:设:c1=c1=“ABCDABCD”,c2=c2=“EFGHEFGH” ,则,则c1+c2

5、=c1+c2=ABCDEFGHABCDEFGH ” 这就是这就是“+ +”运算符的重载。运算符的重载。2.运算符重载的方法为了重载运算符,必须定义一个函数,并告诉编译器,遇到这个重载运算符就调用该函数,由这个函数来完成该运算符应该完成的操作。这种函数称为运算符重载函数,它通常是类的成员函数或者是友元函数。运算符的操作数通常也应该是类的对象。82.运算符重载的方法重载运算符的函数一般形式:函数类型 operator 运算符名称(形参表) 函数体(对运算符的重载处理) 93.重载运算符的规则不允许用户定义新的运算符,只能对c+已有的运算符进行重载C+允许重载的运算符见表10.1(P313),不能重

6、载的运算符有5个,见下页的表重载不能改变运算符运算对象(操作数)的个数重载不能改变运算符的优先级、结合性重载运算符的函数不能有默认的参数(见书P313-314)103.重载运算符的规则11C+C+中不允许重载的运算符中不允许重载的运算符运算符运算符 运算符的含义运算符的含义不允许重载的原因不允许重载的原因?:?:三目运算符三目运算符 在在C+中没有定义一个三目运算符的语法中没有定义一个三目运算符的语法 成员操作符成员操作符保证成员操作符对成员访问的安全性,故保证成员操作符对成员访问的安全性,故不允许重载不允许重载*成员指针操作符成员指针操作符同上同上:作用域运算符作用域运算符因该操作符左边的操

7、作数是类名,而不是因该操作符左边的操作数是类名,而不是一个表达式一个表达式sizeof 求字节数操作符求字节数操作符其操作数可能是一个类型名,而不是一个其操作数可能是一个类型名,而不是一个表达式表达式4.运算符重载函数作为类成员函数和友元函数12运算符重载的函数有两种方式:运算符重载的函数有两种方式:p把运算符重载的函数作为类的成员函数把运算符重载的函数作为类的成员函数p把运算符重载函数作为类的友元函数把运算符重载函数作为类的友元函数4.运算符重载函数作为类成员函数和友元函数13(1 1)运算符重载函数作为运算符重载函数作为类成员函数类成员函数定义格式如下定义格式如下: operator op

8、erator() 函数体函数体 运算的对象运算的对象关键字关键字A A operator +operator + (A &); (A &);/重载了类重载了类A A的的“+”+”运算符运算符返回类型返回类型函数名函数名运算的对象运算的对象其中:其中:operatoroperator是定义运算符重载函数的关键字,是定义运算符重载函数的关键字,它与其后的运算符一起构成函数名。它与其后的运算符一起构成函数名。4.运算符重载函数作为类成员函数和友元函数调用格式:调用格式: .(实参表实参表) );例如:例如: 在进行两个对象的二元运算时,其程序中所用到在进行两个对象的二元运算时,其程序

9、中所用到语法格式为:语法格式为: ; 如:如:c1+c2c1+c2 而执行上述语句时,系统将自动转换成对重载函而执行上述语句时,系统将自动转换成对重载函数的调用格式:数的调用格式: c1.operator+(c2); c1.operator+(c2);1415class A private: int i; public: A(int a=0) i=a; void Show( ) couti=iendl;A operator +(A &a)/定义重载运算符+的成员函数 A t; t.i=i+a.i; return t; ;void main( ) A a1(10),a2(20),a3;a

10、1.Show ();a2.Show ();a3=a1+a2;/重新解释了加法,可以直接进行类的运算a3.Show ();使用重载运算符的例子使用重载运算符的例子运行结果:?运行结果:?i=10i=20i=30相当于相当于a3=a1.operator+(a2)即:左操作数作为调用重载函数即:左操作数作为调用重载函数的对象,右操作数作为调用重载的对象,右操作数作为调用重载函数的实参。函数的实参。i的值是实参的值是实参a1.i,即为,即为10;虚参;虚参a接接收实参收实参a2的值,所以的值,所以a.i=2016class A private:int i;public:A(int a=0) i=a;

11、void Show(void) couti=iendl;void AddA(A &a,A &b)/利用函数进行类之间的运算i=a.i+b.i;void main(void) A a1(10),a2(20),a3;a1.Show ();a2.Show ();/a3=a1+a2; /不可直接运算a3.AddA(a1,a2);/调用专门的功能函数a3.Show ();没有重载运算符的例子没有重载运算符的例子利用函数完成了加法运算利用函数完成了加法运算重载运算符与一般函数的比较:相同:1)均为类的成员函数;2)实现同一功能void AddA( A &a, A &b )v

12、oid AddA( A &a, A &b ) i=a.i+b.i; i=a.i+b.i; 函数调用:函数调用:a3.AddA(a1,a2);a3.AddA(a1,a2);返回值返回值函数名函数名由对象由对象a3调用调用A operator +(A &a)A operator +(A &a) A t; A t; t.i=i+a.i; t.i=i+a.i; return t; return t; 函数调用:函数调用:a3=a1+a2;a3=a1.operator+(a2);形参列表形参列表返回值返回值函数名函数名由对象由对象a1调用调用形参:是对形参:是对象的引用象

13、的引用#includeclass Room private: double Length, Wide; public: Room(double a=0.0, double b=0.0) Length=a; Wide=b; void Show(void) coutLength=LengthtWide=Wideendl; Room operator+(Room &);/重载运算符重载运算符+,函数原型,函数原型;Room Room:operator + (Room &r) /重载运算符,函数定义重载运算符,函数定义 Room rr; rr.Length =Length+r.Leng

14、th; rr.Wide =Wide+r.Wide ; return rr;void main(void) Room r1(3,2),r2(1,4), r3,r4;r1.Show ();r2.Show ();r3=r1+r2; r3.Show ();r4=r1+r2+r3;r4.Show ();相当于相当于r3=r1.operator+(r2 );(1)19运算符的优先级和结合律是不能改变的运算符的优先级和结合律是不能改变的#includeclass Complex public:Complex()real=0;imag=0; Complex(double r,double i) real=r;

15、imag=i; Complex operator+operator+(Complex &c2) Complex c; c.real=real+c2.real; c.imag=imag+c2.imag; return c; void display() cout(real,imagi)endl;private:double real;double imag;使用运算符重载实现复数加运算使用运算符重载实现复数加运算int main() Complex c1(3,4),c2(5,-10),c3; c3=c1+c2; cout“c1=”;c1.display(); cout“c2=”;c2.d

16、isplay(); cout“c3=”;c3.display();相当于相当于c3=c1.operator+(c2 )例、实现复数的例、实现复数的“等于等于” 操作。操作。class Complex double real, imag;public:.bool operator =(const Complex & x) constreturn (real = x.real) & (imag = x.imag);.Complex c1,c2;. if (c1 = c2).4.运算符重载函数作为类成员函数和友元函数(2 2)运算符重载函数作为类的运算符重载函数作为类的友元函数友元函

17、数 友元函数是在类外的普通函数,与一般友元函数是在类外的普通函数,与一般函数的区别是可以调用类中的私有或保护数函数的区别是可以调用类中的私有或保护数据。据。 将运算符的重载函数定义为友元函数时将运算符的重载函数定义为友元函数时,参与运算的对象全部要成为函数参数参与运算的对象全部要成为函数参数。234.运算符重载函数作为类成员函数和友元函数运算符重载函数作为类运算符重载函数作为类友元函数的定义格式:友元函数的定义格式: 说明:说明:形参形参1 1与与形参形参2 2为参加运算的两个对象的引用。为参加运算的两个对象的引用。当重载函数为友元普通函数时,该重载函数不能当重载函数为友元普通函数时,该重载函

18、数不能用对象调用,因此参加运算的两个对象必须以参用对象调用,因此参加运算的两个对象必须以参数的方式传送到重载函数体内,所以数的方式传送到重载函数体内,所以形参通常为形参通常为两个参加运算的对象引用两个参加运算的对象引用。24 ( (形参形参1 1,形参,形参2) 2) 函数体函数体 4.运算符重载函数作为类成员函数和友元函数例如:例如:A A a a ,b , c; ,b , c; c= c=a+ba+b; ; 实际上是实际上是 c=c=operator+(a, b)operator+(a, b); ; c= c=+a+a; ; 实际上是实际上是 c=c=operator+(a)operato

19、r+(a); ; c+=ac+=a; ; 实际上是实际上是 operator+=( c, a )operator+=( c, a ); ;说明:参加运算的操作数均作为函数的参数说明:参加运算的操作数均作为函数的参数(红色字体表示)(红色字体表示)254.运算符重载函数作为类成员函数和友元函数例例10.3 10.3 :将运算符将运算符“+ +”重载为适用于复数的加法,重载为适用于复数的加法,重载函数放在类外,作为类的友元函数。重载函数放在类外,作为类的友元函数。代码如下:代码如下:26#include class Complex public: Complex()real=0;imag=0; C

20、omplex(double r)real=r;imag=0; Complex(double r,double i)real=r;imag=i; friend Complex operator+ (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:

21、display() cout(real,imagi)endl;int main() Complex c1(3,4),c2(5,-10),c3; c3=c1+c2; coutc1=; c1.display(); coutc2=; c2.display(); coutc1+c2=; c3.display(); return 0; 相当于相当于c3=operator+(c1,c2 )5. 重载双目运算符 双目运算是指有两个操作数的运算,操双目运算是指有两个操作数的运算,操作数在运算符的两侧,前面举的实例都是双作数在运算符的两侧,前面举的实例都是双目运算。目运算。 双目运算符既可以重载为成员函数,也双

22、目运算符既可以重载为成员函数,也可以重载为类的友元函数。可以重载为类的友元函数。295. 重载双目运算符双目运算重载为成员函数的定义格式class . operator # (); /#代表可重载的操作符; :operator # ( ) . 使用格式 a; b; a # b 或,a.operator#(b)305. 重载双目运算符双目运算重载为友元函数的定义格式 operator #( , ) . 使用格式为: a; b;a # b 或 operator#(a,b)315. 重载双目运算符例例10.410.4:定义一个字符串类:定义一个字符串类StringString,用来存放不定,用来存放

23、不定长度的字符串,重载运算符长度的字符串,重载运算符“=”,“ ”, ,用于两个字符串的等于,小于和大于的比较运算。用于两个字符串的等于,小于和大于的比较运算。注:从简单到最终完成,可分以下几个步骤注:从简单到最终完成,可分以下几个步骤32#include class String /String 是用户自己指定的类名是用户自己指定的类名 public: String()p=NULL; String(char *str); void display(); private: char *p; ; String:String(char *str) p=str;void String:display

24、() coutp; int main() String string1(“Hello”); String string2(Book); string1.display(); coutendl; string2.display(); return 0;第第1步:创建类步:创建类String,编写,编写简单程序框架简单程序框架#include #include class String public: String()p=NULL; String(char *str); friend bool operator(String &string1,String &string2); v

25、oid display(); private: char *p; ;第第2步:增加运算符重载部分,步:增加运算符重载部分,先增加重载运算符先增加重载运算符“” String:String(char *str) p=str; void String:display() cout(String &string1,String &string2) if(strcmp(string1.p,string2.p)0) return true; else return false; int main() String string1(Hello),string2(Book); coutstr

26、ing2)(string1, string2 )#include #include class String public: String()p=NULL; String(char *str); friend bool operator(String &string1,String &string2); friend bool operator(String &string1,String &string2); friend bool operator=(String &string1,String &string2); void display

27、(); private: char *p; ;第第3步:扩展到步:扩展到3个运算符重载个运算符重载String:String(char *str) p=str;void String:display() cout(String &string1,String &string2) if( strcmp(string1.p,string2.p)0 ) return true; else return false; bool operator(String &string1,String &string2) if( strcmp(string1.p,string2.p

28、)0 ) return true; else return false; bool operator=(String &string1,String &string2) if( strcmp(string1.p,string2.p)=0 ) return true; else return false; int main()String string1(Hello),string2(Book),string3(Computer); coutstring2)endl; cout(string1string3)endl; cout(string1=string2)endl; ret

29、urn 0;相当于相当于:operator(string1, string2 )operator=(string1, string2 )5. 重载双目运算符第第4 4步:进一步修饰、完善,使其更直观,详细步:进一步修饰、完善,使其更直观,详细代码见代码见:P321P322:P321P322396. 重载单目运算符40 单目运算是指:只有一个操作数的运算,单目运算是指:只有一个操作数的运算,所以也称一元运算。如所以也称一元运算。如, !a , +, !a , +i i ,j- - ,j- - 等等等。等。单目运算符既可以重载为成员函数,也可单目运算符既可以重载为成员函数,也可以重载为类的友元函数

30、。以重载为类的友元函数。6. 重载单目运算符41单目单目运算符重载为成员函数的运算符重载为成员函数的定义格式定义格式:class . operator # (); ; :operator # () . 使用格式:使用格式: a;#a 或,a.operator#()6. 重载单目运算符42单目单目运算符重载为友元函数的运算符重载为友元函数的定义格式定义格式:定义格式 operator #( ) . 使用格式为:使用格式为: a; #a 或 operator#(a)例:实现复数的例:实现复数的取反操作取反操作class Complex .public:.Complex operator -() c

31、onstComplex temp;temp .real = -real;temp.imag = -imag;return temp;.Complex a(1,2),b;b = -a; /把b修改成a的负数。6. 重载单目运算符44典型单目运算符为典型单目运算符为“+” 或(或(- - -),它们分别,它们分别有有前置与后置两种前置与后置两种,如果没有特殊说明,它们的前,如果没有特殊说明,它们的前置用法与后置用法均使用同一个重载函数:置用法与后置用法均使用同一个重载函数:operator +();operator +();为了能够区分为了能够区分+(- - -)的前置与后置用法,可)的前置与后置

32、用法,可为它们再写一个重载函数用于实现它们的后置用法,为它们再写一个重载函数用于实现它们的后置用法,该重载函数应有一个形式上的该重载函数应有一个形式上的intint型参数:型参数:operator +(operator +(intint););6. 重载单目运算符45以以+运算为例,重载函数定义:运算为例,重载函数定义:“+”为前置运算符,定义格式:为前置运算符,定义格式: :operator +( ) :operator +( ) 函数体函数体 “+”为后置运算符,定义格式:为后置运算符,定义格式: :operator +( int ):operator +( int )函数体函数体 重载函

33、数的调用格式:重载函数的调用格式: 前置前置“+”运算符,调用格式:运算符,调用格式: .operator +( ).operator +( ); 后置后置“+”运算符,调用格式:运算符,调用格式: .operator +(1).operator +(1);用来区分是前置用来区分是前置还是后置运算,还是后置运算,没有实际意义。没有实际意义。详细内容自学详细内容自学class Counter int value;public: Counter() value = 0; Counter & operator +() /前置的+重载函数 value+; return *this; const

34、 Counter operator +(int) /后置的+重载函数 Counter temp=*this; /保存原来的对象 +(*this); /调用前置的+重载函数,或直接写成value+; return temp; /返回原来的对象 ;.Counter a,b,c;b = +a; /使用的是上述类定义中不带参数的操作符+重载函数c = a+; /使用的是上述类定义中带int型参数操作符+重载函数6. 重载单目运算符47以前置以前置+为例,为例,例例10.510.5: 有一个有一个TimeTime类,包含类,包含2 2个数据成员:个数据成员:minute(minute(分分) )和和se

35、csec(秒),模拟秒表,每次走(秒),模拟秒表,每次走1 1秒秒,满,满6060秒进秒进1 1分钟,此时秒又从分钟,此时秒又从0 0算起,要求输出算起,要求输出分和秒的值。分和秒的值。注意:使用注意:使用+前置运算符完成前置运算符完成#include using namespace std;class Timepublic: Time()minute=0;sec=0;/默认构造函数默认构造函数 Time(int m,int s) minute=m;sec=s;/构造函数重载构造函数重载 Time operator+( ); /声明运算符重载成员函数声明运算符重载成员函数 void displ

36、ay()/定义输出时间函数定义输出时间函数 coutminute:sec=60) sec=sec-60; +minute; return *this;/返回自加后的当前对象返回自加后的当前对象int main()Time time1(34,0); for (int i=0;i61;i+) +time1; time1.display(); return 0;如果改变显示方式为类似秒表方式,可以在如果改变显示方式为类似秒表方式,可以在主函数增加一条语句,即改为:主函数增加一条语句,即改为:for (int i=0;i61;i+) system(“cls”);/清屏清屏 +time1; time1.

37、display(); #include using namespace std;class Timepublic: Time()minute=0;sec=0; Time(int m,int s)minute=m;sec=s; Time operator+(); void display()coutminute:sec=60) sec-=60; +minute; return *this; int main()Time time1(34,0); for (int i=0;i61;i+)system(cls); +time1; time1.display(); return 0;53总结:总结:对

38、二元运算符,重载为成员函数时,仅一个对二元运算符,重载为成员函数时,仅一个参数,另一个被隐含;重载为友元函数时,有参数,另一个被隐含;重载为友元函数时,有两个参数,没有隐含参数。两个参数,没有隐含参数。一般来说,一元运算符最好被重载为成员函一般来说,一元运算符最好被重载为成员函数数, ,对二元运算符最好被重载为友元函数。对二元运算符最好被重载为友元函数。假定要对类 AB 定义减号操作符重载成员函数,实现两个 AB 类对象的减法,并返回相减结果,则该成员函数的声明语句为( ) A) AB operator-(AB &a ,AB &b); B) AB operator-(AB &a

39、mp;a ); C) operator-(AB a ); D) AB & operator-( ); 54练习B B7.重载流插入运算符重载流插入运算符”C+编译系统在其类库中提供了iostream类,该类由包括:输入流类istream和输出流类ostream,而cin和cout分别是istream类和ostream类的对象,所以,如果在程序中使用”cout”,则必须在程序的开始添加头文件”iostream.h”。55C+编译系统已经对”进行了重载,使之作为流插入运算符和流提取运算符,能用来输出和输入C+标准类型的数据。用户自己定义的类型的数据(如对象),是不能直接用”来输出和输入的,如果想用它们输出和输入自己声明的类型的数据,必须对它们重载。输入输出运算符只能用友元函数重载567.重载流插入运算符重载流插入运算符”对”重载的函数形式如下: istream & operator(istream & ,自定义类 &); ostream & operator(o

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论