04 重载运算符.ppt_第1页
04 重载运算符.ppt_第2页
04 重载运算符.ppt_第3页
04 重载运算符.ppt_第4页
04 重载运算符.ppt_第5页
已阅读5页,还剩40页未读 继续免费阅读

下载本文档

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

文档简介

1、第4章 运算符重载,课件制作,2,主要内容,运算符重载的概念(13.1-13.2) 运算符重载的方法(13.3) 重载双目运算符(13.4) 重载单目运算符(13.5-13.8) 不同类型数据间的转换(13.9) 重载赋值运算符(13.11) 小结与作业,课件制作,3,4.1 运算符重载的概念,有理数类 CRational 有理数定义:由一个分子和分母组成的a/b形式的数,其中 a是分子,b为分母,如 1/3, 3/4, 10/4; 一个有理数不能以0为分母,但可以以0为分子; 每个整数a 都等价于 a/1; 有理数用于包含分数的精确运算; 有理数支持的运算有加、减、乘、除、比较; 一个有理数

2、可以转化为一个整数、浮点数或字符串;,课件制作,4,4.1 运算符重载的概念,/Rational.h #include using namespace std; /类CRational 声明 class CRational public: CRational(); CRational(long numerator, long denominator); long getNumerator(); long getDenominator(); CRational add(CRational ,课件制作,5,4.1 运算符重载的概念,/file:Rational.cpp #include using

3、 namespace std; #include Rational.h CRational:CRational() numerator = 0; denominator = 1; CRational:CRational(long numerator, long denominator) long factor = gcd(numerator, denominator); this-numerator = (denominator 0) ? 1 : -1) * numerator / factor; this-denominator = abs(denominator) / factor; lo

4、ng CRational:getNumerator() return numerator; long CRational:getDenominator() return denominator; ,课件制作,6,4.1 运算符重载的概念,CRational CRational:add(CRational ,CRational CRational:div(CRational ,课件制作,7,4.1 运算符重载的概念,string CRational:toString() char s120, s220; itoa(numerator, s1, 10); / Convert int to stri

5、ng s1 itoa(denominator, s2, 10); / Convert int to string s2 if (denominator = 1) return string(s1); else return string(strcat(strcat(s1, /), s2); /* Find GCD of two numbers */ long CRational:gcd(long n, long d) long n1 = abs(n); long n2 = abs(d); int gcd = 1; for (int k = 1; k = n1 ,课件制作,8,4.1 运算符重载

6、的概念,/file: RationalTest.cpp #include using namespace std; #include Rational.h int main() / Create and initialize two rational numbers r1 and r2. CRational r1(4, 2); CRational r2(2, 3); / Test toString, add, substract, multiply, and divide cout r1.toString() + r2.toString() = r1.add(r2).toString() en

7、dl; cout r1.toString() - r2.toString() = r1.sub(r2).toString() endl; cout r1.toString() * r2.toString() = r1.mul(r2).toString() endl; cout r1.toString() / r2.toString() = r1.div(r2).toString() endl; / Test intValue and double cout Value() is Value() endl; cout r2.doubleValue() is r2.doub

8、leValue() endl; / Test compare cout pare(r2) is pare(r2) endl; cout pare(r1) is pare(r1) endl; cout pare(r1) is pare(r1) endl; return 0; ,能否象整数的算术运算一样,直接用“+,-,*, /”符号来实现有理数的算术运算呢?如:r3=r1+r2; 编译系统就会自动完成r1和r2两个有理数相加的运算?,课件制作,9,4.1 运算符重载的概念,重载,就是重新赋予新的含义 运算符重载的实质:对已有的运算符赋予多重含义 运算符重载的必要性: C+中预定义的运算符其运算对

9、象只能是基本数据类型,而不适用于用户自定义类型(如类) 运算符重载的实现机制:将指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参 编译系统对重载运算符的选择,遵循函数重载的选择原则,用“+, -,*, /”能够实现有理数的算术运算吗? 能,实现有理数算术运算的方法 重载“+, -,*, /”运算符,课件制作,10,4.2 运算符重载的方法,运算符重载的方法:在类中定义一种特殊的称为运算符函数的函数,在需要时,系统就自动调用该函数,以实现相应的运算 重载运算符的函数一般格式如下: 在定义了运算符函数后,可以说函数 operator+ 重载了运算符+,返回类型 operat

10、or 运算符 (形参表列) 对运算符的重载处理 ,课件制作,11,4.2 运算符重载的方法,重载运算符“+”,使之能用于两个有理数相加。,有无空格均可,/Rational.h #include using namespace std; /类CRational 声明 class CRational public: CRational operator + (CRational ,/file:Rational.cpp #include using namespace std; #include Rational.h“ CRational CRational:operator+(CRational

11、,课件制作,12,4.2 运算符重载的方法,/file: RationalTest.cpp #include using namespace std; #include Rational.h int main() / Create and initialize two rational numbers r1 and r2. CRational r1(4, 2); CRational r2(2, 3); CRational r; / Test toString, operator+ r = r1.operator+(r2); cout r1.toString() + r2.toString()

12、= r.toString() endl; r = r1+ r2; cout r1.toString() + r2.toString() = r.toString() endl; return 0; ,课件制作,13,4.2 运算符重载的方法,重载为类成员函数 C+预定义运算符其运算对象中至少有一个是程序员自定义类型时,需要重载运算符为该类的成员函数 重载为类成员函数时, 参数个数 = 原操作数个数 - 1(后置+、-除外) 成员函数用 this 指针隐式的访问了类的一个对象,它充当了运算符函数左边的操作数 重载为友元函数 如果需要重载一个运算符,使之能够用于操作某类对象的私有成员,可以将此运算

13、符重载为该类的友元函数 重载为友元函数时,参数个数 = 原操作数个数,且至少应该有一个自定义类型的形参,课件制作,14,4.2 运算符重载的方法,/Rational.h #include using namespace std; /类CRational 声明 class CRational public: friend CRational operator + (CRational ,将运算符“+”重载为适用于有理数加法,重载函数作为 CRational 类的友元函数,课件制作,15,4.2 运算符重载的方法,/file:Rational.cpp #include using namespac

14、e std; #include Rational.h“ CRational operator+ (CRational ,课件制作,16,4.2 运算符重载的方法,/file: RationalTest.cpp #include using namespace std; #include Rational.h int main() / Create and initialize two rational numbers r1 and r2. CRational r1(4, 2); CRational r2(2, 3); CRational r; / Test toString, operator

15、+ r = operator+ (r1,r2); cout r1.toString() + r2.toString() = r.toString() endl; r = r1+ r2; cout r1.toString() + r2.toString() = r.toString() endl; return 0; ,课件制作,17,4.2 运算符重载的方法,C+不允许程序员创建新的运算符,只能对已有的C+运算符进行重载 (P321) 对于C+已有运算符,以下运算符不允许重载(5个): 成员访问运算符 . 指针取内容运算符 * 作用域运算符 : 条件运算符 ? : sizeof 重载不能改变运

16、算符运算对象(即操作数)的个数 重载不能改变运算符的优先级和结合性 重载运算符函数不能有默认参数 应当使重载运算符的功能类似于该运算符作用于标准类型数据时所实现的功能,课件制作,18,4.2 运算符重载的方法,说明 在表达式中,如果两个操作数中其中有一个不是类对象,则重载的双目运算符(如“+”) 左侧应为类的对象 如果运算符左侧的操作数属于C+标准类型,则运算符函数不能作为类的成员函数,必须声明为友元函数 C+规定:赋值运算符(=)、下标运算符()、函数调用运算符( () ) 只能重载为类的成员函数;流插入运算符“”、类型转换运算符(sizeof)只能重载为类的友员函数 考虑到各方面的因素,一

17、般将单目运算符重载为成员函数,将双目运算符重载为友元函数 由于友元的使用会破坏类的封装,从原则上说,要尽量将运算符函数作为成员函数,r = r2 + i; 表达式 i + r2,运算符左侧的操作数 i 是整数,无法调用成员函数(i.operator+ 函数),课件制作,19,4.2 运算符重载的方法,使用运算符重载能使用户程序易于编写、阅读和维护 通过运算符重载,扩大了C+已有运算符的作用范围,使之能用于类对象。 运算符重载使C+具有更强大的功能、更好的可扩充性和适应性,这是C+最吸引人的特点之一,在实际工作中,类的声明和类的使用往往是分离的。假如在声明CRational类时,对运算符 +,-

18、,*, / 都进行了重载,那么使用这个类的用户在编程时可以完全不考虑函数是怎么实现的,放心大胆地直接使用 +,-,*, / 进行有理数的运算即可,十分方便。,课件制作,20,4.3 重载双目运算符,双目运算符(或称二元运算符)是C+中最常用的运算符。双目运算符有两个操作数,通常在运算符的左右两侧 在重载双目运算符时,在函数中应该有两个参数,例:重载有理数类 CRational 的“ ”和“ += ”,3 + 5, a += b,i10,课件制作,21,4.3 重载双目运算符,/Rational.h #include using namespace std; /类CRational 声明 cla

19、ss CRational public: bool operator (CRational ,/file:Rational.cpp #include using namespace std; #include Rational.h“ bool CRational:operatornumerator * r2.denominator - r2.numerator*this-denominator; if ( nnumerator = this-numerator * r2.denominator + this-denominator * r2.numerator; this-denominato

20、r = this-denominator * r2.denominator; return (*this); ,课件制作,22,4.3 重载双目运算符,/file: RationalTest.cpp #include using namespace std; #include Rational.h int main() CRational r1(4, 2); CRational r2(2, 3); / Test toString, operator bool bRet; bRet = r1.operator(r2); cout r1.toString() r2.toString() is in

21、t(bRet) endl; bRet = r1 r2; cout r1.toString() r2.toString() is int(bRet) endl; CRational r; / Test toString, operator+= r = r1; r1.operator+=(r2); cout r.toString() += r2.toString() is r1.toString() endl; r1 = r; r1+=r2; cout r.toString() += r2.toString() is r1.toString() endl; return 0; ,课件制作,23,4

22、.4 重载单目运算符,单目运算符只有一个操作数,如 !a,-b, +a; a+;,ClassA a, b; b=+a; b=a+;,ClassA a, b; b= -a; b= +a;,课件制作,24,4.4 重载单目运算符,/Rational.h #include using namespace std; /类CRational 声明 class CRational public: CRational operator - (); private: long numerator; long denominator; static long gcd(long n, long d); ;,/fi

23、le:Rational.cpp #include using namespace std; #include Rational.h“ CRational CRational:operator- () numerator *= -1; return *this; ,课件制作,25,4.4 重载单目运算符,/file: RationalTest.cpp #include using namespace std; #include Rational.h int main() / Create and initialize two rational numbers r1 and r2. CRation

24、al r2(2, 3); CRational r; / Test toString, operator+ r = r2.operator- (); cout - r2.toString() is r.toString() endl; r = -r2; cout - r2.toString() is r.toString() endl; return 0; ,课件制作,26,4.4 重载单目运算符,+和- 运算符的重载 虽然+a 和 a+ 运算后对象a的值一致,但先自加或后自加的重载运算符函数的返回值不一致,必须在重载时予以区分 C+约定: 在自增(自减)运算符重载函数中,增加一个int 型形参

25、,就是后置自增(自减)运算符函数 +为前置运算时,运算符重载函数的一般格式为: +为后置运算时,运算符重载函数的一般格式为:, operator +( ) . , operator +(int) .; ,课件制作,27,4.4 重载单目运算符,/Rational.h #include using namespace std; /类CRational 声明 class CRational public: CRational operator + (); CRational operator + (int); private: long numerator; long denominator; s

26、tatic long gcd(long n, long d); ;,/file:Rational.cpp #include using namespace std; #include Rational.h“ CRational CRational:operator+ () numerator = numerator + denominator; return *this; CRational CRational:operator+ (int) CRational temp(numerator,denominator); numerator = numerator + denominator;

27、return temp; ,课件制作,28,4.4 重载单目运算符,/file: RationalTest.cpp #include using namespace std; #include Rational.h int main() / Create and initialize two rational numbers r1 and r2. CRational r, r1(2, 3) , r2(3,5); / Test toString, operator+ r = r1.operator+(int); cout r1.toString() + is r.toString() endl;

28、 r = r1+; cout r1.toString() + is r.toString() endl; r = r2.operator+(); cout + r2.toString() = r.toString() endl; r =+ r2; cout + r2.toString() = r.toString() endl; return 0; ,课件制作,29,4.4 重载单目运算符,/file: Increase.h #include using namespace std; class Increase public: Increase(int x):value(x) Increas

29、e ,/file: Increase.cpp #include Increase.h Increase /返回原有对象值 ,课件制作,30,4.4 重载单目运算符,/file: IncreaseTest.cpp #include using namespace std; #include Increase.h int main() Increase n(20); n.display(); (n-).display(); /显示临时对象值 n.display(); /显示原有对象 -n; n.display(); -(-n); n.display(); (n-)-; /第二次减量操作对临时对象进

30、行 n.display(); return 1; ,n-t1; n=n-1; n-t2; n=n-1;,课件制作,31,4.4 重载单目运算符,运算符重载 C+中,数组下标符号被视为运算符 必要时可以重载此运算符以实现象访问数组一样访问对象内容,使用 r0 和 r1 语法形式访问有理数 r 的分子分母,/Rational.h #include using namespace std; /类CRational 声明 class CRational public: long ,/file:Rational.cpp #include using namespace std; #include Rat

31、ional.h“ long ,课件制作,32,4.4 重载单目运算符,/file: RationalTest.cpp #include using namespace std; #include Rational.h int main() CRational r(2, 3); / Test toString, operator cout r is r.toString() endl; cout r0 is r0 ,r1 is r1 endl; r0 = 5; r1 = 6; cout r is r.toString() endl; cout r0 is r.operator(0) ,r1 is

32、 r1 endl; return 0; ,课件制作,33,4.4 重载单目运算符, 运算符重载 是类 istream 的成员(ostream 是C+标准类库中用于处理输出的类, istream 是C+标准类库中用于处理输入的类) C+允许重载 (流提取运算符),用于从输入流读取对象内容; 运算符和不是类CRational 的成员,同时重载时又需要访问类CRational 的私有成员,因此可将其声明为类CRational 的友元,课件制作,34,4.4 重载单目运算符,/Rational.h #include #include using namespace std; /类CRational 声

33、明 class CRational public: friend ostream,课件制作,35,4.4 重载单目运算符,/file:Rational.cpp #include using namespace std; #include Rational.h“ ostream ,课件制作,36,4.4 重载单目运算符,/file: RationalTest.cpp #include using namespace std; #include Rational.h int main() CRational r1,r2; coutr1; coutr2; coutr1 + r2 is r1.add(

34、r2) endl; return 0; ,课件制作,37,4.5 不同类型数据间的转换,标准类型数据间的转换 隐式类型转换:在C+中,某些不同类型数据之间可以自动转换,这种转换是由C+编译系统自动完成的,用户不需干预 显式类型转换:程序人员在程序中指定将一种指定的数据转换成另一指定的类型,其形式为:类型名(数据)或 (类型名)数据 用户自己声明的类型 编译系统并不知道怎样进行转换,解决这个问题需要定义专门的函数来处理即转换运算符函数,让编译系统知道怎样去进行这些转换 转换运算符函数就是在类中定义一个成员函数,将类转换为某种期望的数据类型,int i = 6; i = 7.5 + i; / i

35、is 13,int i = int(89.5) ; / or (int) 89.5 , i is 89; (short int) 89.8,课件制作,38,4.5 不同类型数据间的转换,转换运算符函数语法格式为: 转换运算符函数必须是类的成员,对转换运算符函数的调用是隐含的,没有参数 转换运算符函数没有返回值,函数名就是所期望的将对象转换为的目标类型,ClassName : operator ( ) . ,欲转换类型,关键字,类名,具体的转换算法,课件制作,39,将类 CRational 转换为 int 型和 double型,4.5 不同类型数据间的转换,/Rational.h #includ

36、e #include using namespace std; /类CRational 声明 class CRational public: operator int(); operator double(); private: long numerator; long denominator; static long gcd(long n, long d); ;,/file:Rational.cpp #include using namespace std; #include Rational.h“ CRational:operator int () return numerator/den

37、ominator; CRational:operator double () return 1.0*numerator/denominator; ,课件制作,40,4.5 不同类型数据间的转换,/file: RationalTest.cpp #include using namespace std; #include Rational.h int main() CRational r1(9,4); cout r1 is r1endl int i = r1+3; cout r1 + 3 is iendl; double f = r1 + 1.25; cout r1 + 1.25 is fendl; return 0; ,课件制作,41,4.6 重载赋值运算符,默认情况下,赋值运算符(=) 执行从一个对象到另一个对象的逐成员拷贝(浅拷贝) 当对象的成员中使用了动态数据类型时(用 new 开辟空间),就不能直接相互赋值,否则在程序的执行期间会出现运行错误 自定义拷贝构造函数不会改变赋值拷贝运算符 = 的默认行为 为了改变默认赋值运算符( =) 的工作方式,需要重载

温馨提示

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

最新文档

评论

0/150

提交评论