第6章运算符重载及友元_第1页
第6章运算符重载及友元_第2页
第6章运算符重载及友元_第3页
第6章运算符重载及友元_第4页
第6章运算符重载及友元_第5页
已阅读5页,还剩65页未读 继续免费阅读

下载本文档

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

文档简介

1、1 面向对象程序设计面向对象程序设计C+ 第6章 运算符重载与友元2主要内容主要内容n运算符重载的目的、定义和实质运算符重载的目的、定义和实质n运算符重载的规则运算符重载的规则 n运算符重载的两种形式运算符重载的两种形式 n友元的作用和定义友元的作用和定义 n类型转换运算符重载类型转换运算符重载3提出问题提出问题n复数的加减运算问题:复数的加减运算问题:n对于非基本数据类型,如复数、分数,如何对于非基本数据类型,如复数、分数,如何在程序中进行运算?在程序中进行运算?n能否直接用运算符(能否直接用运算符(+ +、- -、* *、/ /)进行运算?)进行运算?4分析问题分析问题n自定义一个复数类自

2、定义一个复数类ComplexComplex完成复数的加减运算完成复数的加减运算n设计复数类设计复数类class Complex/复数类复数类public: Complex(double r=0.0,double i=0.0) /构造函数构造函数 real=r; image=i; private:double real, image; /定义实部、虚部定义实部、虚部; 5思考思考n是否能通过下面的代码完成复数的加减运算:是否能通过下面的代码完成复数的加减运算:int main() /定义一个复数对象定义一个复数对象c1,其实部为其实部为2,虚部为,虚部为2.5 Complex c1(2, 2.5

3、); Complex c2(3, 1.4); Complex c3, c4; c3 = c1 + c2; c4 = c1 - c2; return 0; 6说明说明nC+C+预定义的预定义的“+”“+”、“-”“-”运算只支持基运算只支持基本数据类型,并不支持用户自定义类型。本数据类型,并不支持用户自定义类型。 n复数类的加减运算不能采用系统预定义复数类的加减运算不能采用系统预定义的运算符的运算符“+”“+”、“-”“-”完成,那么编写完成,那么编写成员函数来实现加、减运算。成员函数来实现加、减运算。7重新设计复数类重新设计复数类ComplexComplexclass Complex publ

4、ic: Complex(double r=0.0,double i=0.0) /构造函数构造函数 real=r; image=i; double Real()return real; /返回复数的实部返回复数的实部 double Imag()return image;/返回复数的虚部返回复数的虚部 Complex add(Complex &c); /函数重载,实现复数加复数函数重载,实现复数加复数 Complex add(double d); /函数重载,实现复数加实数函数重载,实现复数加实数 Complex sub(Complex &c); /函数重载,实现复数减复数函数重载,实现复数减复数

5、 Complex sub(double d); /函数重载,实现复数减实数函数重载,实现复数减实数private: double real, image; /定义实部、虚部定义实部、虚部;8n完成复数与复数相加完成复数与复数相加Complex Complex:add(Complex &c) Complex temp; temp.real = real + c.real; temp.image = image + c.image; return temp; 成员函数定义成员函数定义9n完成复数与实数相加完成复数与实数相加Complex Complex:add(double d) Complex

6、temp; temp.real = real + d; temp.image = image; return temp; 10int main() Complex c1(2, 2.5); Complex c2(3, 1.4); Complex c3, c4; c3=c1.add(c2); c4=c1.sub(c2); coutc3= c3.Real() +i c3.Imag()endl; coutc4= c4.Real() +i c4.Imag()endl; return 0;不如不如c3=c1+c2直观直观!11n用函数的方式将复数的加减运算表示出用函数的方式将复数的加减运算表示出来远不如用

7、运算符来远不如用运算符“+”“+”、“-”“-”直观直观 n如果复数的运算能够用已有的运算符表如果复数的运算能够用已有的运算符表示出来,则程序的易读性会大大增强,示出来,则程序的易读性会大大增强,同时更符合人的思维习惯同时更符合人的思维习惯 nC+C+提供了提供了运算符重载机制运算符重载机制,使得系统预,使得系统预定义的运算符能够完成用户自定义数据定义的运算符能够完成用户自定义数据类型的运算类型的运算 说明说明12运算符重载运算符重载n运算符重载就是为用户自定义类型运算符重载就是为用户自定义类型重新定重新定义运算符义运算符,使同一个运算符既可以作用于使同一个运算符既可以作用于预定义的数据类型,

8、也可以作用于用户自预定义的数据类型,也可以作用于用户自定义的数据类型。定义的数据类型。n运算符重载本质上是一种特殊的运算符重载本质上是一种特殊的函数重载函数重载。13运算符重载运算符重载n为了重载运算符,必须定义一个运算符重载为了重载运算符,必须定义一个运算符重载函数,函数,由这个函数来完成该运算符应该完成由这个函数来完成该运算符应该完成的操作。的操作。运算符的操作数通常是类的对象。运算符的操作数通常是类的对象。n可以将运算符重载函数作为可以将运算符重载函数作为类的成员函数或类的成员函数或者是友元函数者是友元函数。14重载为类的成员函数重载为类的成员函数格式如下:格式如下: operator

9、operator () 函数体函数体 A operator + (A &);/重载了类重载了类A A的的“+”+”运算运算符符返回类型返回类型运算的对象运算的对象关键字关键字函数名函数名运算的对象运算的对象15在复数类中重载运算符在复数类中重载运算符class Complex/复数类复数类public: Complex(double r=0.0,double i=0.0)real=r;image=i; const double Real()return real; const double Imag()return image; Complex operator+( Complex &c);

10、/重载运算符重载运算符“+”“+” Complex operator+( double d); /重载运算符重载运算符“+”“+” Complex operator-( Complex &c); /重载运算符重载运算符“-”“-” Complex operator-( double d); /重载运算符重载运算符-private: double real,image; ;16n运算符重载为成员函数时运算符重载为成员函数时最多有一个形最多有一个形参参 n运算符重载的运算符重载的实质就是函数重载实质就是函数重载,只不,只不过函数名换成了关键字过函数名换成了关键字operatoroperator和具

11、体和具体要重载的运算符要重载的运算符n运算符重载的函数参数运算符重载的函数参数就是该运算符涉就是该运算符涉及的操作数及的操作数,因此运算符重载在参数个,因此运算符重载在参数个数上是有限制的,这是它不同于函数重数上是有限制的,这是它不同于函数重载之处。载之处。说明说明17class Aint i;public:A(int a=0) i=a; void Show(void)couti=iendl;void AddA(A &a, A &b)/利用函数进行类之间的运算利用函数进行类之间的运算i=a.i+b.i;int main()A a1(10),a2(20),a3;a1.Show ();a2.Sho

12、w ();/a3=a1+a2;/不可直接运算不可直接运算a3.AddA(a1,a2);/调用专门的功能函数调用专门的功能函数a3.Show (); return 0; 没有重载运算符的例子没有重载运算符的例子利用函数完成了加法运算利用函数完成了加法运算用和作对象调用函数用和作对象调用函数18class Aint i;public:A(int a=0) i=a;void Show(void)couti=iendl;void AddA(A &a, A &b)/利用函数进行类之间的运算利用函数进行类之间的运算i=a.i+b.i;A operator +(A &a) /重载运算符重载运算符+ +A t

13、;t.i=i+a.i;return t;int main()A a1(10),a2(20),a3;a1.Show ();a2.Show ();a3=a1+a2;/重新解释了加法,可以直接进行类的运算重新解释了加法,可以直接进行类的运算a3.AddA(a1,a2);/调用专门的功能函数调用专门的功能函数a3.Show (); return 0;相当于相当于a3=a1.operator+(a2)有重载运算符的例子有重载运算符的例子19重载运算符与一般成员函数的比较:重载运算符与一般成员函数的比较:相同:相同:1 1)均为类的成员函数;)均为类的成员函数;2 2)实现同一功能)实现同一功能void

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

15、由对象由对象a1a1调用调用总结:总结:运算符重载为成员函数运算符重载为成员函数时,左操作数必须是对时,左操作数必须是对象本身,象本身,由左操作数调由左操作数调用右操作数用右操作数。最后将函。最后将函数返回值赋给运算结果数返回值赋给运算结果的对象。的对象。21运算符重载的规则运算符重载的规则n重载的功能应当与原有功能类似,不能重载的功能应当与原有功能类似,不能改变原运算符的操作数个数,同时至少改变原运算符的操作数个数,同时至少要有一个操作数的类型是自定义类型。要有一个操作数的类型是自定义类型。n重载之后运算符的优先级和结合性都不重载之后运算符的优先级和结合性都不会改变,并且要保持原运算符的语法

16、结会改变,并且要保持原运算符的语法结构。参数和函数值类型都可以重新说明。构。参数和函数值类型都可以重新说明。 22运算符重载的规则运算符重载的规则n当用当用成员函数实现运算符的重载时成员函数实现运算符的重载时,运,运算符重载函数的参数只能有两种情况:算符重载函数的参数只能有两种情况:没有参数或带有一个参数没有参数或带有一个参数。n在重载在重载单目单目运算符时,通常运算符时,通常不能有参数;不能有参数;在重载在重载双目双目运算符时,只能带有运算符时,只能带有一个参一个参数。数。参数可以是对象,对象的引用,或参数可以是对象,对象的引用,或其它类型的参数。其它类型的参数。n在在C+C+中不允许重载有

17、三个操作数的运算中不允许重载有三个操作数的运算符。符。23不能重载的运算符不能重载的运算符不能重载的运算符不能重载的运算符 说明说明 :作用域运算符作用域运算符.成员访问运算符成员访问运算符.*成员指针访问运算符成员指针访问运算符?:条件运算符条件运算符sizeof求表达式或数据类型所占存储求表达式或数据类型所占存储空间字节数空间字节数typeid用于运行时类型信息(用于运行时类型信息(RTTI)的识别,指出指针或引用指向的识别,指出指针或引用指向的对象的实际派生类型的对象的实际派生类型24单目运算符的重载单目运算符的重载只具有一个操作数的运算符为单目运算符,最常只具有一个操作数的运算符为单目

18、运算符,最常用的为及。用的为及。A a, b;b=+a;b=a+;A a;+a;a+;可以看出,虽然运算后对象可以看出,虽然运算后对象a a的值一致,但先自加的值一致,但先自加或后自加的或后自加的重载运算符函数的返回值不一致,重载运算符函数的返回值不一致,必必须在重载时予以区分须在重载时予以区分。25+为前置运算时,为前置运算时,它的运算符重载函数的一般格式为:它的运算符重载函数的一般格式为: operator +( ) operator +( )+为后置运算时为后置运算时,它的运算符重载函数的一般格式为:,它的运算符重载函数的一般格式为: operator +( operator +(int

19、int) )A a, b;b=+a;b=a+;A operator +( ) . A operator +(int) . 26class A float x, y;public: A(float a=0, float b=0) x=a; y=b; A operator +( )A t; t.x=+ x; t.y=+y; return t; A operator +(int) A t; t.x=x+; t.y=y+; return t;int main() A a(2,3), b; b=+a; b=a+; return 0; 27A operator +( ) A t; t.x=+ x; t.y

20、=+y; return t; b=+a; b=a.operator+( );返回值返回值函数名函数名23at3344t t作为函数值返回赋给作为函数值返回赋给b bA operator +( ) + x; +y; return *this;将对象本身作为函将对象本身作为函数值返回赋给数值返回赋给b b28A operator +(int) A t; t.x=x+; t.y=y+; return t;b=a+; b=a.operator+(3);23at3243返回值返回值函数名函数名t t作为函数值返回赋给作为函数值返回赋给b b29n运算符重载为成员函数后,它可以自由地运算符重载为成员函数后

21、,它可以自由地访问类的所有成员。实际使用时,总是通过访问类的所有成员。实际使用时,总是通过该类的某个对象来访问重载的运算符。该类的某个对象来访问重载的运算符。 n运算符重载为类的成员函数时,函数的参运算符重载为类的成员函数时,函数的参数个数比原来操作数少一个(后缀数个数比原来操作数少一个(后缀“+”“+”和和后缀后缀“-”“-”除外)。除外)。说明说明30n用成员函数实现运算符的重载时,用成员函数实现运算符的重载时,运算符运算符的左操作数为当前对象的左操作数为当前对象,并且要用到隐含的,并且要用到隐含的thisthis指针。指针。 n运算符重载函数不能定义为静态的成员函运算符重载函数不能定义为

22、静态的成员函数,因为静态的成员函数中没有数,因为静态的成员函数中没有thisthis指针指针。说明说明31说明说明n如果是双目运算符,左操作数一定是对象本如果是双目运算符,左操作数一定是对象本身,由身,由thisthis指针给出,另一个操作数需要由指针给出,另一个操作数需要由运算符重载的参数表来传递。运算符重载的参数表来传递。 n如果是单目运算符,操作数由对象的如果是单目运算符,操作数由对象的thisthis指指针给出,就不再需要任何参数。但重载针给出,就不再需要任何参数。但重载“+”“+”和和“-”“-”运算符时,运算符时,C+C+约定,如果在参数表约定,如果在参数表中放一个整型参数,则表示

23、重载的运算符为中放一个整型参数,则表示重载的运算符为后缀运算符。后缀运算符。 32n根据类的封装性,一般将数据成员声明根据类的封装性,一般将数据成员声明为私有成员,外部不能直接访问,只能为私有成员,外部不能直接访问,只能通过类的公有成员函数对私有成员进行通过类的公有成员函数对私有成员进行访问。访问。nC+C+从高效的角度出发从高效的角度出发,提供友元机制,提供友元机制,使被声明为友元的全局函数或者其他类使被声明为友元的全局函数或者其他类可以直接访问当前类中的私有成员,又可以直接访问当前类中的私有成员,又不改变其私有成员的访问权限。不改变其私有成员的访问权限。 友元友元33n友元可以是一个友元可

24、以是一个全局函数全局函数、另一个类的、另一个类的成成员函数员函数或者是一个或者是一个类类。分别称为友元函数。分别称为友元函数和友元类。友元类的所有成员函数都是友和友元类。友元类的所有成员函数都是友元函数,可以访问被访问类的任何成员。元函数,可以访问被访问类的任何成员。n友元声明以关键字友元声明以关键字friendfriend开始开始,只能出现只能出现在在被访问类被访问类的定义中的定义中。具体格式如下:。具体格式如下: nfriend friend (););nfriend class friend class ; ; 友元友元34n友元函数不是成员函数友元函数不是成员函数,用法也与普通的,用法

25、也与普通的函数完全一致,函数完全一致,只不过它能访问类中所有只不过它能访问类中所有的数据的数据。友元函数破坏了类的封装性和隐友元函数破坏了类的封装性和隐蔽性,使得非成员函数可以访问类的私有蔽性,使得非成员函数可以访问类的私有成员成员。n一个类的友元可以自由地用该类中的所有一个类的友元可以自由地用该类中的所有成员。成员。 友元友元35class Afloat x,y;public: A(float a, float b) x=a; y=b; float Sum() return x+y; friend float Sum(A &a) return a.x+a.y; ;int main() A t

26、1(4,5),t2(10,20); coutt1.Sum()endl; coutSum(t2)endl; return 0;友元函数友元函数成员函数成员函数友元函数的调用,直接调用友元函数的调用,直接调用成员函数的调用,利用对象名调用成员函数的调用,利用对象名调用友元函数只能用友元函数只能用对象对象名名引用类中的数据。引用类中的数据。私有数据私有数据36友元函数与普通函数友元函数与普通函数n友元函数近似于友元函数近似于普通的函数普通的函数,它不带有,它不带有thisthis指针,指针,因此必须将对象名或对象的因此必须将对象名或对象的引用作为友元函数的参数引用作为友元函数的参数,这样才能访,这样

27、才能访问到对象的成员。问到对象的成员。n友元函数必须在类的定义中声明,友元函数必须在类的定义中声明,其函其函数体可在类内定义,也可在类外定义数体可在类内定义,也可在类外定义。n友元函数可以访问该类中的所有成员友元函数可以访问该类中的所有成员(公有的、私有的和保护的)(公有的、私有的和保护的),而一般,而一般函数只能访问类中的公有成员。函数只能访问类中的公有成员。37class Afloat x,y;public: A(float a, float b) x=a; y=b; float Getx() return x; float Gety() return y; float Sum() ret

28、urn x+y; friend float Sum(A &); ;float Sumxy(A &a) return a.Getx()+a.Gety(); float Sum(A &a) return a.x+a.y; int main() A t1(1,2),t2(10,20), t3(100,200); coutt1.Sum()endl; coutSum(t2)endl; coutSumxy(t3)endl; return 0;成员函数成员函数友元函数友元函数,可以直接调用类中私有成员可以直接调用类中私有成员普通函数,必须通过公有函数访问私有成员普通函数,必须通过公有函数访问私有成员对象调用

29、成员函数对象调用成员函数调用友元函数调用友元函数调用普通函数调用普通函数友元函数友元函数38n友元函数不受类中访问权限关键字的限制,友元函数不受类中访问权限关键字的限制,可以把它放在类的私有、公有或保护部分,可以把它放在类的私有、公有或保护部分,其作用都是一样的。换言之,其作用都是一样的。换言之,在类中对友元在类中对友元函数指定访问权限是不起作用的函数指定访问权限是不起作用的。n友元函数的作用域与普通函数的作用域相同。友元函数的作用域与普通函数的作用域相同。n谨慎使用友元函数谨慎使用友元函数n通常使用友元函数来通常使用友元函数来取取对象中的数据成员值,而对象中的数据成员值,而不修改不修改对象中

30、的成员值,保证数据安全。对象中的成员值,保证数据安全。39n大多数情况是友元函数是某个类的成员函数,大多数情况是友元函数是某个类的成员函数,即即A A类中的某个成员函数是类中的某个成员函数是B B类中的友元函数,类中的友元函数,这个成员函数可以直接访问这个成员函数可以直接访问B B类中的私有数类中的私有数据。据。这就实现了类与类之间的沟通。这就实现了类与类之间的沟通。n注意:注意:一个类的成员函数作为另一个类的友元一个类的成员函数作为另一个类的友元函数时,函数时,应先定义友元函数所在的类。应先定义友元函数所在的类。class Avoid fun( B &);class Bfriend void

31、 fun( B &);既是类既是类A A的成员函数的成员函数又是类又是类B B的友元函数的友元函数40class B ;/先定义类先定义类A,则首先对类,则首先对类B作引用性说明作引用性说明class A ./类类A的成员定义的成员定义 public: void fun( B & );/函数的原型说明函数的原型说明 ;class B. friend void A:fun( B & );/定义友元函数定义友元函数; void A:fun ( B &b) /函数的完整定义函数的完整定义 ./函数体的定义函数体的定义类类A A中的成员函数中的成员函数fun()fun()是类是类B B的友元的友元函数

32、。即在函数。即在fun()fun()中中可以直接引用类可以直接引用类B B的的私有成员。私有成员。41class B;/必须在此进行引用性说明必须在此进行引用性说明class Afloat x,y;public: A(float a, float b) x=a; y=b; void Sum(B &); /说明友元函数的函数原型,是类说明友元函数的函数原型,是类A的成员函数的成员函数;class Bfloat m,n;public: B(float a,float b) m=a;n=b; friend void A:Sum(B &);/说明类说明类A的成员函数是类的成员函数是类B的友元函数的友元

33、函数;void A:Sum( B &b)/定义该友元函数定义该友元函数 x=b.m+b.n; y=b.m-b.n; int main() A a1(3,5); B b1(10,20); a1.Sum(b1); /调用该函数,调用该函数,因是类因是类A的成员函数,故用类的成员函数,故用类A的对象调用的对象调用 return 0;a1.x=30a1.y=-10直接引用类直接引用类B B的私有成员的私有成员类类A中有一个函数可以直中有一个函数可以直接引用类接引用类B的私有成员的私有成员42友元类友元类class A . friend class B;class B . 类类B B是类是类A A的友元

34、的友元类类B B可以自由使用可以自由使用类类A A中的成员中的成员对于类对于类B B而言,类而言,类A A是透明的是透明的类类B B必须通过必须通过类类A A的对象的对象使用类使用类A A的成员的成员43const float PI =3.1415926;class Afloat r ;float h;public: A(float a,float b)r=a; h=b;float Getr()return r;float Geth()return h;friend class B;/定义类定义类B为类为类A的友元的友元;class B int number;public: B(int n=1

35、)number=n;void Show(A &a) coutPI*a.r*a.r*a.h*numberendl; /求类求类A的某个对象的某个对象*n的体积的体积;int main()A a1(25,40),a2(10,40);B b1(2);b1.Show (a1); b1.Show (a2); return 0;直接引用类直接引用类A A的私有成员的私有成员类类B B中的任何函数都中的任何函数都能使用类能使用类A A中的所有中的所有私有成员。私有成员。44n不管是按哪一种方式派生,基类的私有成不管是按哪一种方式派生,基类的私有成员在派生类中都是不可见的。员在派生类中都是不可见的。n如果在一

36、个派生类中要访问基类中的私有如果在一个派生类中要访问基类中的私有成员,可以将这个成员,可以将这个派生类声明为基类的友元派生类声明为基类的友元。class Base friend class Derive; .class Derive:public Base .直接使用直接使用Base中的私有成员中的私有成员45class M friend class N; /N为为M的友元,可以直接使用的友元,可以直接使用M中的私有成员中的私有成员private: int i , j; void show(void)couti=itj=jt;public: M(int a=0,int b=0) i=a; j=

37、b;class N :public M /N为为M的派生类的派生类public: N(int a=0,int b=0):M(a,b) void Print(void) show(); couti+j=i+jendl;int main() N n1(10,20); M m1(100,200);/ m1.show();/私有成员函数,在类外不可调用私有成员函数,在类外不可调用 n1.Print(); return 0;直接引用类直接引用类M M的私有成员函数和私有成员的私有成员函数和私有成员46基类对象基类对象 M派生类对象派生类对象 Nx(私有)私有)Show( )(私私有有)x(私有私有)Sh

38、ow( )(私有私有)y(公有公有)Showy( )(公有公有)showy( ) show(); coutxendl; 当派生类是基类的友元时当派生类是基类的友元时:N n; n.showy( ); n.show( ); 错误错误, ,类外不可调用类外不可调用47n友元的出现主要是为了解决一些实际问题,友元本身不是面向对友元的出现主要是为了解决一些实际问题,友元本身不是面向对象的内容。象的内容。n通过友元机制,一个类或函数可以直接访问另一类中的非公有成通过友元机制,一个类或函数可以直接访问另一类中的非公有成员。员。n可以将全局函数、类、类的成员函数声明为友元。可以将全局函数、类、类的成员函数声

39、明为友元。n友元关系是不能传递的。友元关系是不能传递的。B B类是类是A A类的友元,类的友元,C C类是类是B B类的友元,类的友元,C C类和类和A A类之间,如果没有声明,就没有任何友元关系,不能进行类之间,如果没有声明,就没有任何友元关系,不能进行数据共享。数据共享。n友元关系是单向的,如果声明友元关系是单向的,如果声明B B类是类是A A类的友元,类的友元,B B类的成员函数类的成员函数就可以访问就可以访问A A类的私有成员和保护成员。但类的私有成员和保护成员。但A A类的成员不能访问类的成员不能访问B B类的私有成员和保护成员,除非声明类的私有成员和保护成员,除非声明A A类是类是

40、B B类的友元。类的友元。n友元关系是不能继承的。友元关系是不能继承的。B B类是类是A A类的友元,类的友元,C C类是类是B B类的派生类,类的派生类,则则C C类和类和A A类之间没有任何友元关系,除非类之间没有任何友元关系,除非C C类声明类声明A A类是友元。类是友元。 友元小结友元小结48n运算符重载有两种方式:运算符重载为运算符重载有两种方式:运算符重载为类的类的成员函数成员函数,运算符重载为,运算符重载为类的友元函数类的友元函数。n当运算符重载为类的成员函数时,对于单目当运算符重载为类的成员函数时,对于单目运算符,操作数一定是对象本身,对于双目运算符,操作数一定是对象本身,对于

41、双目运算符,左操作数一定是对象。运算符,左操作数一定是对象。n当运算符重载为友元函数时,参数中同样必当运算符重载为友元函数时,参数中同样必须有一个是用户自定义类型的对象,但不限须有一个是用户自定义类型的对象,但不限定其必须是左操作数。定其必须是左操作数。运算符重载的使用运算符重载的使用49运算符重载为运算符重载为成员函数成员函数时,是由一个操作数调用时,是由一个操作数调用另一个操作数。另一个操作数。A a ,b , c;c=a+b;实际上是实际上是c=a.operator+(b);c=+a;实际上是实际上是c=a.operator+( );即函数的实参只有一个或没有。即函数的实参只有一个或没有

42、。c+=a;实际上是实际上是c.operator+=( a );50n将运算符的重载函数定义为友元函数,将运算符的重载函数定义为友元函数,参与参与运算的对象全部成为函数参数。运算的对象全部成为函数参数。A a ,b , c;c=a+b;实际上是实际上是 c=operator+(a, b);c=+a;实际上是实际上是 c=operator+(a);c+=a;实际上是实际上是 operator+=( c, a );51n语法形式语法形式friendfriend operator operator () ; n运算符重载为类的友元函数运算符重载为类的友元函数最多只能有两个参数最多只能有两个参数n如果

43、重载双目运算符,则如果重载双目运算符,则第一个参数代表左操作第一个参数代表左操作数,第二个参数代表右操作数数,第二个参数代表右操作数重载为类的友元函数重载为类的友元函数52friend const double operator+(Triangle &t1,Triangle &t2) /运算符重载为友元函数运算符重载为友元函数 return t1.area+t2.area; private: int x,y,z; double area; ; int main() Triangle t1(3,4,5),t2(4,5,6); double s; coutt1:;t1.disparea(); co

44、utt2:;t2.disparea(); s=t1+t2; cout总面积总面积=sendl; return 0;class Triangle;const double operator+(Triangle &t1,Triangle &t2);class Triangle public: Triangle(int i,int j,int k) double s; x=i;y=j;z=k; s=(x+y+z)/2.0; area=sqrt(s*(s-x)*(s-y)*(s-z); void disparea() coutArea=areaendl; 【例例6-96-9】示例运算符重载为类示例运算

45、符重载为类的友元函数。的友元函数。53class Aint i;public:public:A(int a=0) i=a; void Show(void)couti=iendl; friend A operator +(A &,A &);/友元函数,两个参数,为引用友元函数,两个参数,为引用;A operator +(A &a , A &b)A t;t.i=a.i+b.i;return t; int main()A a1(10),a2(20),a3;a1.Show ();a2.Show ();a3=a1+a2;/重新解释了加法,可以直接进行类的运算重新解释了加法,可以直接进行类的运算a3.Sh

46、ow (); return 0;相当于相当于a3=operator+(a1,a2)54+为前置运算时,为前置运算时,它的运算符重载函数的一般格式为:它的运算符重载函数的一般格式为:A operator +(A &a)+为后置运算时为后置运算时,它的运算符重载函数的一般格式为:,它的运算符重载函数的一般格式为:A operator +(A &a, int)A a, b;b=+a;b=a+;A operator +( A a ) . A operator +(A a, int) . 重载为类的友元函数重载为类的友元函数55class Aint i;public:A(int a=0) i=a; vo

47、id Show(void)couti=i、-*必须为成员函数必须为成员函数+=、=、/=、*=、=、&=、|=、%=、=、=成员函数成员函数所有其他二元运算符所有其他二元运算符友元函数友元函数59类型转换运算符重载类型转换运算符重载n基本类型到类类型的转换基本类型到类类型的转换n类类型到基本类型的转换类类型到基本类型的转换60基本类型到类类型的转换基本类型到类类型的转换n同类型的对象可以相互赋值,相当于类同类型的对象可以相互赋值,相当于类中的数据成员相互赋值。中的数据成员相互赋值。n如果如果直接将数据赋给对象直接将数据赋给对象,所赋入的数,所赋入的数据需要强制类型转换,据需要强制类型转换,这种

48、转换需要调用这种转换需要调用构造函数构造函数。也就是。也就是利用利用构造函数构造函数能完成从能完成从基本类型到类类型的转换。基本类型到类类型的转换。n使用构造函数进行类型转换必须有一个使用构造函数进行类型转换必须有一个前提,那就是在这个类中定义一个只有一前提,那就是在这个类中定义一个只有一个参数的构造函数。个参数的构造函数。61注意:当构造函数只有一个参数时,可以用注意:当构造函数只有一个参数时,可以用= 强制赋值强制赋值。class Bint x;public: B(int a) x=a; cout调用构造函数调用构造函数n; B() cout调用析构函数调用析构函数n; void Prin

49、t() coutxendl; ;int main()B b1(1) ; b1.Print(); b1=10; b1.Print(); cout退出主函数退出主函数n; return 0;调用构造函数调用构造函数单参数可以这样赋值单参数可以这样赋值1调用构造函数调用构造函数调用析构函数调用析构函数10退出主函数退出主函数调用析构函数调用析构函数b1=B(10)产生一个产生一个临时对象临时对象62class A int x, y; public: A(int a, int b) x=a; y=b; int main() A a(2,3); coutaendl; return0;错误!类的对象不能直

50、接输出错误!类的对象不能直接输出利用类型转换运利用类型转换运算符重载将类算符重载将类A的对象的对象a转换成转换成某种基本数据类某种基本数据类型型Aint63类类型到基本类型的转换n构造函数能够把基本类型数据转换成指定类对构造函数能够把基本类型数据转换成指定类对象,但不能把类对象转换为基本类型数据。象,但不能把类对象转换为基本类型数据。nC+引入一种特殊的成员函数引入一种特殊的成员函数类类型转换类类型转换函函数。类类型转换函数实际上就是一个类型转换运数。类类型转换函数实际上就是一个类型转换运算符算符重载函数重载函数。n类类型转换函数专门用来将类类型转换为基本类类型转换函数专门用来将类类型转换为基本数据类型,它只能被重载为成员函数。数据类型,它只能被重载为成员函数。64类类型到基本类型的转换 重载重载类型转换运算符函数格式:类型转换运算符函数格式:operator返回返回基本基本类型名类型名()() return 基本类型值基本类型值转换函数的调用是隐转换函数的调用是隐含的,没有参数。含的,没有参数。函数前不需要加函数前不需要加函数值类型。函数值类型。65class Aint i;public:public:A(int a=0) i=a; void Show(void)couti=iendl; operator int( ) returni;int

温馨提示

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

评论

0/150

提交评论