第11章77 运算符重载[章节讲课].ppt

上传人:scccc 文档编号:11893341 上传时间:2021-10-18 格式:PPT 页数:77 大小:1.14MB
返回 下载 相关 举报
第11章77 运算符重载[章节讲课].ppt_第1页
第1页 / 共77页
第11章77 运算符重载[章节讲课].ppt_第2页
第2页 / 共77页
第11章77 运算符重载[章节讲课].ppt_第3页
第3页 / 共77页
第11章77 运算符重载[章节讲课].ppt_第4页
第4页 / 共77页
第11章77 运算符重载[章节讲课].ppt_第5页
第5页 / 共77页
点击查看更多>>
资源描述

《第11章77 运算符重载[章节讲课].ppt》由会员分享,可在线阅读,更多相关《第11章77 运算符重载[章节讲课].ppt(77页珍藏版)》请在三一文库上搜索。

1、第11章 运算符重载,什么是运算符重载 运算符重载的方法 几个特殊的运算符的重载 自定义类型转换运算符 运算符重载实例,1,章节课件,什么是运算符重载,使系统内置的运算符可以用于类类型 例如:+ 运算符能够实现2个对象间的加。例如:类A的对象a1、a2、a3,希望: a3 = a1 + a2; 即:分别把对象a1和a2的各个数据成员值对应相加,然后赋给对象a3。,2,章节课件,问题的提出,把某些事交给系统去做,用户只要知道相加就可 扩充运算符的功能 增强了C+ 语言的可扩充性 使用户定义的类更像系统的内置类型,3,章节课件,运算符重载的限制,不是所有的运算符都能重载 重载不能改变运算符的优先级

2、和结合性 重载不能改变运算符的操作数个数 不能创建新的运算符,4,章节课件,可以重载的运算符,+ - * / % int den; void ReductFraction(); public: Rational(int n = 0, int d = 1) num = n; den = d; Rational operator+(const Rational ,11,章节课件,函数实现,Rational Rational:operator+(const Rational ,12,章节课件,bool Rational:operator(const Rational ,13,章节课件,方案二:重载成

3、友员函数,class Rational friend Rational operator+(const Rational ,14,章节课件,函数的实现,Rational operator+(const Rational 其他函数实现略,15,章节课件,重载后有理数类的使用,int main() Rational r1(1,6), r2(1,6), r3; r3 = r1 + r2; r1.display(); cout + ; r2.display(); cout = ; r3.display(); cout endl; r3 = r1 * r2; r1.display(); cout * ;

4、 r2.display(); cout = ; r3.display(); cout endl; return 0; ,16,章节课件,全局函数 vs成员函数,大多数运算符都可以重载成成员函数或全局函数。 赋值(=)、下标()函数调用()和成员访问(-)必须重载成成员函数。 具有赋值意义的运算符,如复合的赋值运算符以及+和-,不一定非要定义为成员函数,但最好定义为成员函数。 具有两个运算对象的运算符最好重载为全局函数,这样可以使得应用更加灵活。如果把加运算定义成全局函数,r是有理数类的对象,则2+r是一个合法的表达式。,17,章节课件,第11章 运算符重载,什么是运算符重载 运算符重载的方法

5、几个特殊的运算符的重载 自定义类型转换运算符 运算符重载实例,18,章节课件,几个特殊的运算符的重载,赋值运算符 下标运算符 函数调用运算符 +和运算符的重载 重载函数的原型设计考虑 输入输出运算符重载,19,章节课件,赋值运算符,对任一类,如果用户没有自定义赋值运算符函数,那么系统为其生成一个缺省的赋值运算符函数,在对应的数据成员间赋值。 一般情况下,这个缺省的赋值运算符重载函数能满足用户的需求。但是,当类含有类型为指针的数据成员时,可能会带来一些麻烦。,20,章节课件,对DoubleArray类对象执行array1 = array2的问题,会引起内存泄漏 使这两个数组的元素存放于同一块空间

6、中 当这两个对象析构时,先析构的对象会释放存储数组元素的空间。而当后一个对象析构时,无法释放存放数组元素的空间,21,章节课件,赋值运算符“=”的原型,赋值运算符只能重载成成员函数 函数原型: X 数组输入: for (i=20; i arrayi; 数组输出: for (i=20; i=30; +i) cout arrayi t;,29,章节课件,几个特殊的运算符的重载,赋值运算符 下标运算符 函数调用运算符 +和运算符的重载 重载函数的原型设计考虑 输入输出运算符重载,30,章节课件,函数调用运算符,函数调用运算符()是一个二元运算符。它的第一个运算对象是函数名,第二个参数是形式参数表。运

7、算的结果是函数的返回值。 一个类重载了函数调用运算符,就可以把这个类的对象当做函数来使用,31,章节课件,函数调用运算符重载,函数调用运算符必须重载成成员函数 函数调用运算符重载函数的原型为 函数的返回值 operator() (形式参数表);,32,章节课件,函数调用运算符重载实例,在DoubleArray类增加一个功能:取数组中的一部分元素形成一个新的数组 例如,在一个下标范围为10到20的数组arr中取出下标为第12到15的元素,形成一个下标范围为2到5的数组存放在数组arr1中,可以调用 arr1 = arr(12, 15, 2)。,33,章节课件,DoubleArray operat

8、or()(int start, int end, int lh) if (start end | start high ) cout 下标越界; exit(-1); DoubleArray tmp(lh, lh + end - start); for (int i = 0; i end - start + 1; +i) tmp.storagei = storagestart + i - low; return tmp; ,34,章节课件,几个特殊的运算符的重载,赋值运算符 下标运算符 函数调用运算符 +和运算符的重载 重载函数的原型设计考虑 输入输出运算符重载,35,章节课件,“+”和“-”重

9、载,、- -:是一元操作符 这两个操作符可以是前缀,也可以是后缀。而且前缀和后缀的含义是有区别的。所以,必须有两个重载函数。 问题:两个重载函数有相同的原型 区分方法: 前缀:一元操作符。 后缀:二元操作符。,36,章节课件,“+”和“-”重载 cont.,成员函数重载 +ob重载为:ob.operator+() ob- 重载为:ob.operator-(int) 友元函数重载 +ob重载为:operator+(X /计数器的值 int alarm; /报警值 public: Counter(int a) value = 0; alarm = a; Counter ,39,章节课件,类实现,C

10、ounter /返回修改前的状态 ,40,章节课件,类的使用,int main() Counter cnt(3); /定义一个Counter类的对象,报警值为3 cnt.print(); /显示对象的当前值,此时输出为0 +cnt; cnt.print(); / 此时输出为1 (+cnt).print(); /调用前缀的+,输出2 (cnt+).print(); /调用后缀的+,当前对象的value已经 /加1,报警。但输出的是2 cnt.print(); /输出值为3 return 0; ,41,章节课件,几个特殊的运算符的重载,赋值运算符 下标运算符 函数调用运算符 +和运算符的重载 重载

11、函数的原型设计考虑 输入输出运算符重载,42,章节课件,重载函数的原型设计考虑,参数设计 对于任何函数的参数,如果仅需要从参数中读,而不改变它,一般用const引用来传递。 只有会修改左值参数的运算符,如赋值运算符,左值参数不是常量,所以用地址传递 返回值的类型设计 运算符的结果产生一个新值,就需要产生一个作为返回值的新对象 对于逻辑运算符,人们希望至少得到一个int或bool的返回值 所有的赋值运算符(如,=,+=等)均改变左值,应该能够返回一个刚刚改变了的左值的非常量引用,43,章节课件,值返回时的优化,在返回一个对象时,通常有两种写法。如某函数返回一个Rational类的对象,它的值为两

12、个参数的成员对应相加。它的两种写法为 return Rational( left.num + right.num, left.den + right.den); Rational tmp; tmp.num = left.num + right.num; tmp.den = left.den + right.den; return tmp;,44,章节课件,两种写法的比较,前者的意思是“创建一个临时对象,并返回它” 。它只调用了一次构造函数。 而后者,先创建了一个对象tmp,这将调用构造函数,然后对tmp赋值,最后返回tmp。而在返回tmp时,又要创建一个临时对象,并调用拷贝构造函数用tmp对它

13、进行初始化。在函数执行结束时,还要调用析构函数析构tmp。,45,章节课件,几个特殊的运算符的重载,赋值运算符 下标运算符 函数调用运算符 +和运算符的重载 重载函数的原型设计考虑 输入输出运算符重载,46,章节课件,输入输出运算符重载,输入输出运算符必须被重载成全局函数。 输出运算符的重载 输入运算符的重载,借助于流插入运算符()和流提取运算符()输入和输出用户自定义类的对象,47,章节课件,输出重载函数的原型,ostream ,48,章节课件,实例,ostream的结果是 1/3。,为Rational类重载输出,49,章节课件,输入输出运算符重载,输入输出运算符必须被重载成全局函数。 输出

14、运算符的重载 输入运算符的重载,借助于流插入运算符()和流提取运算符()输入和输出用户自定义类的对象,50,章节课件,输入重载函数的原型,istream ,51,章节课件,实例,istream的结果是 1/3。,为Rational类重载输入,52,章节课件,第11章 运算符重载,什么是运算符重载 运算符重载的方法 几个特殊的运算符的重载 自定义类型转换运算符 运算符重载实例,53,章节课件,类型转换-系统预定义类型间的转换,隐式类型转换 赋值时 运算时 显式类型转换 强制转换法:(类型名)表达式 函数法:类型名(表达式),54,章节课件,自定义类型转换运算符,类类型能否和其他的类类型或内置类型

15、互相转换? 内置类型之所以能互相转换是因为系统预先制定了转换的规则,并写好了完成转换的程序。 类类型与其它类类型或内置类型之间如何转换,编译器预先无法知道。类的设计者必须定义转换的方法。,55,章节课件,类型转换,内置类型到类类型的转换 类类型到其它类型的转换,56,章节课件,内置类型到类类型的转换,利用构造函数进行转换。 例如,对于Rational类的对象r,可以执行r=2。 此时,编译器隐式地调用Rational的构造函数,传给它一个参数2。构造函数将构造出一个num=2,den= 1的Rational类的对象,并将它赋给r。,57,章节课件,explicit构造函数,任何单参数的构造函数

16、都可以被编译器用来执行隐式转换,即把内置类型转换成对应的类类型。 在某些情况下,隐式转换是不受欢迎的。 将单参数的构造函数定义为explicit,将告诉编译器不允许执行隐式转换。 如将Ratioanal类的构造函数定义成 explicit Rational(int n1 = 0, int n2 = 1) 则对于Rational类的对象r1和r2,执行 r1 = 2 + r2;编译器就会报错,58,章节课件,类型转换,内置类型到类类型的转换 类类型到其它类型的转换,59,章节课件,类类型到内置类型或其他类类型的转换,可以通过类型转换函数实现 类型转换函数必须重载成成员函数 类型转换函数的格式 o

17、perator 目标类型名 ( ) const return (结果为目标类型的表达式); 类型转换函数的特点 无参数,无返回值 是const函数,60,章节课件,Rational类到double的转换,转换函数的定义: operator double () const return (double(num)/den); 有了这个函数,我们可以将一个Rational类的对象r赋给一个double类型的变量x。如r的值为(1,3),经过赋值x = r后,x的值为0.333333,61,章节课件,经过运算符重载后的Rational类,class Rational friend istream,62

18、,章节课件,Rational类的使用,#include #include Rational.h int main() Rational r1, r2, r3, r4; double x; cout r1; cout r2; r3 = r1 + r2; cout r1 + r2 = r3 endl; r3 = r1 * r2; cout r1 * r2 = r3 endl; r4 = (r1 + r2) * r3; cout (r1 + r2) * r3的值为: r4 endl; x = 5.5 - r1; cout 5.5 - r1的值为: x endl; cout (r1 r2 ? r1 :

19、 r2) endl; return 0; ,输入r1: 1 3 输入r2: 2 6 1/3+1/3 = 2/3 1/3*1/3 = 1/9 (r1 + r2) * r3的值为2/27 5.5 - r1的值为:5.16667 1/3,63,章节课件,第11章 运算符重载,什么是运算符重载 运算符重载的方法 几个特殊的运算符的重载 自定义类型转换运算符 运算符重载实例,64,章节课件,运算符重载实例,完善DoubleArray类,65,章节课件,DoubleArray.h,#ifndef _array_h #define _array_h #include class DoubleArray fr

20、iend ostream ,66,章节课件,public: DoubleArray(int lh = 0, int rh = 0):low(lh), high(rh) storage = new double high - low + 1; DoubleArray(const DoubleArray #endif,67,章节课件,DoubleArray.cpp,/文件名:DoubleArray.cpp /DoubleArray类的实现 #include #include DoubleArray.h“ DoubleArray:DoubleArray(const DoubleArray ,68,章

21、节课件,operator=,DoubleArray ,69,章节课件,operator,double ,70,章节课件,operator,ostream ,71,章节课件,operator,istream ,72,章节课件,operator=,bool operator=(const DoubleArray ,73,章节课件,operator(),DoubleArray DoubleArray:operator() (int start, int end, int lh) assert (start = low ,74,章节课件,Main函数,int main() DoubleArray ar

22、ray1(20,30), array2; cin array1; cout array1 ; cout array1; array2 = array1; cout 执行 array2 = array1, array2 array2; cout array1 = array2 是 (array1 = array2) ? true : false) endl; array225 = 0; cout 执行array25 = 0后, array1 = array2 是 (array1 = array2) ? true : false) endl; array2 = array1(22, 25, 2);

23、 cout 执行array2 = array1(22, 25, 2)后, array2 的值为: array2; return 0; ,75,章节课件,执行结果,请输入数组元素20,30: 1 2 3 4 5 6 7 8 9 10 11 array1的内容为: 1 2 3 4 5 6 7 8 9 10 11 执行 array2 = array1,array2的内容为: 1 2 3 4 5 6 7 8 9 10 11 array1 = array2是true 执行array225 = 0后,array1 = array2是false 执行array2 = array1(22, 25, 2)后, array2 的值为:3 4 5 6,76,章节课件,小结,运算符重载的作用 如何选择用成员函数或全局函数 如何写一个重载函数 介绍了一种区分+和的前后缀应用的方法 通过运算符重载实现类类型和内置类型及其他类类型之间的转换,77,章节课件,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 社会民生


经营许可证编号:宁ICP备18001539号-1