C面向对象程序设计

上传人:真** 文档编号:243143993 上传时间:2024-09-16 格式:PPT 页数:26 大小:112KB
返回 下载 相关 举报
C面向对象程序设计_第1页
第1页 / 共26页
C面向对象程序设计_第2页
第2页 / 共26页
C面向对象程序设计_第3页
第3页 / 共26页
点击查看更多>>
资源描述
,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,C+,面向对象程序设计,蚌埠学院计算机系,C+,面向对象程序设计,第十章 运算符重载与类模板,1,学习目标,理解为什么要进行运算符重载,在什么情况下要进行运算符重载,掌握通过成员函数重载运算符,借助友元函数实现运算符重载,理解引用在运算符重载中的作用,引用作为参数和返回值的好处和用法,理解类型转换的必要性,能够在程序设计中正确应用类型转换,理解为什么要引入类模板的概念,掌握类模板的应用,2,10.1,为什么要进行运算符重载,10.1.1,运算符重载的例子,在程序中,经常会使用运算符,但,C+,中已经定义的运算符都是针对基本数据类型的,那么能否将它们用于复杂的类对象呢?在学习本章之前,我们往往是编写实现相应运算功能的函数来解决复杂类型的运算问题。首先来看一个复数加法运算的例子,请注意程序中,加法运算时表达式的书写形式。,【,例,6-1】,复数的加运算。见教材,P133,3,程序说明:,在,【,例,10-1】,为了解决复数的存储问题,在复数类,Complex,中,定义了两个私有成员变量:,real,(复数的实部)和,imag,(复数的虚部);并定义了公有的复数加法函数,add(),和友元输出函数,print(),显示复数。在,main,函数中定义了三个复数对象,使用加法函数,add,进行,3,个复数的相加,并输出结果。,在程序中三个复数相加的表达式为:,c4 = c1.add(c2).add(c3);,用这种方式书写表达式,不仅形式复杂、不符合人们的日常书写习惯,而且不易理解;复数的运算越复杂,书写的表达式越困难,给使用自定义类编写程序带来诸多不便。如果能够像使用基本类型那样用运算符来书写复数运算表达式(如,c4 = c1+c2+c3;,),不仅书写简单,也更容易理解;这正是在,C+,中引入了运算符重载的意义所在。下面通过使用运算符重载进行复数加运算例子来了解如何进行运算符的重载。,4,【,例,10-2】,使用运算符重载进行复数加运算,见教材,P134,输出结果:,11+2i,程序说明:,该程序的作用和,【,例,10-1】,相同,只是用运算符重载函数代替了加法函数。,比较两个程序不难发现,,【,例,10-2】,中书写的复数相加表达式,含义清晰,便于书写。让复数类的使用变得更加简易。,程序中,“,+,”,运算符重载的定义如下:,Complex operator +(Complex ,它与一般函数的定义非常相似,不同的是运算符重载函数的名字(,“,operator +,”,)是由,“,operator,”,关键字和紧随其后的运算符,“,+,”,组成;关键字,“,operator,”,表明该函数是一个运算符重载函数。在,【,例,10-2】,中,该函数是作为类,Complex,的成员函数,因此把以这种方式的运算符重载称作重载为类运算符。,5,【,例,10-3】,重载为友元运算符进行复数加运算,见教材,P136,输出结果:,11+2i,程序说明:,本例实现的功能与,【,例,10-1】,和,【,例,10-2】,完全相同。,本例中,,“,+,”,运算符重载函数的定义如下:,Complex operator +(Complex ,由于该函数是一般的普通函数,不是类的成员函数,只是为能够访问类的私有数据成员,而把其声明为类的友元函数,因此在定义时参数表中必须指定两个参数:第,1,个参数作为运算符的左操作数,第,2,参数作为运算符的右操作数。,6,10.1.2,注意事项,C+,对运算符重载作出了一定的限制和规定,在重载运算符时,需要注意以下几点:,不是所有运算符都可以被重载。,C+,的大部分运算符都可以被重载。可以重载的运算符如下:,new,new, delete,delete,+ - * / % &,| = += -=,*- /= %= = &= |= & | + - -* -,() ,其中,运算符,(),是函数调用运算符,,是下标运算符。,+,、,-,、* 和,&,的一元、二元形式都可以被重载。自增运算符,+,和自减运算符,-,的前置、后置形式都可以被重载。,以上可重载运算符中,除了赋值运算符,=,之外,基类中所有被重载的运算符都将被派生类继承。,7,不可以重载的运算符如下:,.(,成员运算符,) .* (,成员对象选择符,) : (,解析运算符,),?,:,(条件运算符),重载不能改变运算符的优先级。,假定已定义了复数类,Complex,并且已定义了加法和乘法运算符重载函数,,Complex c1(1, 2), c2(3, 4), c3(5, 6), answer;,answer = c1 + c2 * c3;,在这个表达式中,乘法运算优先级高于加法运算,它等效于,answer = c1 + (c2 * c3);,如同系统定义数据类型一样,可以使用括号强制改变重载运算符的计算顺序,例如:,answer = (c1 + c2) * c3;,重载不能改变运算符的结合律。,8,重载不能改变运算符的操作数个数。,重载的一元运算符仍然是一元运算符,重载的二元运算符仍然是二元运算符。,C+,中唯一的三元运算符(?:)不能被重载。运算符,+,、,-,、*、,&,和,既可以用作一元运算符和二元运算符,对这几个运算符,要分别把他们重载为一元运算符和二元运算符。,不能创建新的运算符,只有现用的运算符才能被重载。,运算符重载函数的参数至少有一个必须是类的对象或者是类的对象的引用。,运算符只能被显式重载(不存在隐式重载),例如,运算符,+,和,=,已被分别重载,这不意味着运算符,+=,或,= =,已被重载。,运算符重载函数不能带有缺省参数。,重载运算符时,要保持语义上的一致性。例如,重载运算符,+,时,仍应对有关对象执行加法运算。当然,也可以定义为其它某种运算,但这样做既没有必要,也容易造成混乱。,C+,规定,“,=,、,(),、,、,-”,四种运算符必须重载为类运算符。,9,10.2,赋值运算符和四则运算符的重载,对名为,T,的类,其赋值运算符重载函数的格式如下:,T operator =(T ,由于赋值运算符只能重载为类运算符,所以这是赋值运算符重载函数的唯一格式。,对名为,T,的类,其二元运算符(用,#,表示)重载函数的格式如下:,T operator #(T /,重载为类成员运算符,或,T,operatore,#(T /,重载为非类成员运算符,四则运算符属于二元运算符,也可以使用这两种形式。,下面仍以复数运算为例,说明赋值运算符和四则运算符的重载。,【,例,10-4】,复数的四则运算 见教材,P138,10,10.3,自增,1,和自减,1,运算符重载,自增,1,运算符“,+”,和自减,1,运算符“,-”,都各有两种形式:前缀(前运算)和后缀(后运算)。例如,,+a,是前运算符:在进行其他运算前,变量,a,首先增,1,。,a+,是后运算符:做完其他运算后,,a,才增,1,。这四种形式的每一种都可以重载。,增,1,运算符和减,1,运算符都只有一个操作数,通常被重载为类运算符。一元类运算符重载函数的参数表理应没有参数(操作数即是类对象本身),但为了区分前运算和后运算这两种形式,,C+,中规定:,前运算符重载函数的参数表没有参数;,后运算符重载函数的参数表设一个整数参数,这个参数称为哑元,只作为一个标志,用以区别前运算符。,所以,对名为,T,的类,重载前运算符和后运算符的函数原型取如下格式:,T operator +(); /,重载前增,1,运算符,T operator +(,int,); /,重载后增,1,运算符,T operator -(); /,重载前减,1,运算符,T operator -(,int,); /,重载后减,1,运算符,为了说明增,1,运算符和减,1,运算符重载,下面给出一个分数类作自增,自减的例子。,【,例,6-5】,分数类的自增,自减。 见教材,P142,11,10.4,关系运算符的重载,在,C+,中对于使用内部数据类型定义的变量,可以使用六个关系运算符“,、,=,、,= =,和,!=”,进行比较运算。而要对自定义类定义的变量进行比较运算,用户就必须重载这些运算符。,下面以分数的,为例说明关系运算符的重载。,【,例,10-6】,比较两个分数大小,输出值大的分数。见教材,P144,12,10.5,算术赋值运算符的重载,在,C+,中允许把算术运算符和赋值运算符组合在一起使用,这种书写方法简洁高效;同样也可以在自定义类型中重载这些运算符。为了简单起见,仍然使用分数的例子。,【,例,10-7】,分数的加法运算。见教材,P145,13,10.6,下标运算符的重载,“,”,下标运算符通常用于数组,,c+,也允许重载这个运算符,在重载这个运算符时,需要注意的是:当,“,”,运算符位于,“,=,”,左边时,是修改数组中元素的值,需要返回这个元素的指针或引用;当,“,”,运算符位于,“,=,”,右边时,是取得数组中元素的值,需要返回这个元素的值或引用;为了能使,“,”,运算符即可用于,“,=,”,左边,也可用于,“,=,”,右边,在重载,“,”,运算符时,必须返回该元素的引用。,下面给出一个数组类的例子来说明这一问题。,【,例,10-8】,一个数组类的例子。见教材,P147,14,10.7,插入与抽取运算符的重载,10.7.1,插入运算符的重载,C+,中对左移运算符,“,”,进行重载,以便输出,C+,内部类型的数据。对于自定义类型也可以重载运算符,“,”,进行重载,以便把外来的信息输入到所有的,C+,内部数据类型的变量,这些重载函数作为系统类的成员函数。例如,如果,i,是一个整型变量,,C+,便将输入语句,cin,i;,翻译为,cin.operator,(i);,然后调用此函数,读取一个值,存入变量,i,中。,为了支持自定义类型,用户应重载输入运算符“,”,。在重载时,如果作为一般的函数来定义(而非类的成员函数),则这个重载运算符在被使用时应被声明为类的友元运算符。因为“,”,的第一个操作数是系统类的对象,cin,(系统类,iostream,的对象),因此,作为友元函数,类,X,的输入运算符重载函数的原型应为:,istream,& operator (,istream,请注意:这个函数的第一个参数是输入流的引用,第二个参数是类,X,的引用。函数返回输入流的引用,其目的是为了能连续输入。对此,可以仿照,6.7.1,节做出解释。,【,例,10-10】,分数的输入。见教材,P151,16,10.8,类型转换,在,C+,中,当使用数值类型进行计算时,各种类型之间可以隐式或强制转换;例如:,double d;,int,a = 2;,d = a + 5.3;,这种书写方式,使代码看起来优雅而自然。在用户自定义类中,没有进行类似的定义而无法使用这种方法。,17,10.8.1,基本类型转换和自定义类型的相互转换,在定义了类型转换后,对所有,TRangeInt,类型变量的计算都可以先转换成,int,类型,再进行计算,因此,可以不需要进行运算符的重载(如下面例子中的“,+”,、“,-”,运算符)。,【,例,10-11】TRangeInt,类型的加、减运算。,见教材,P154,18,10.8.2,自定义类型之间的转换,有两种方法可以实现自定义类型之间的转换:使用类型转换符函数和构造函数。不仅可以在基本类型转换和自定义类型之间实现类型的转换,也可以在两个自定义类型之间实现。,【,例,10-12】,使用类型转换符函数实现二维向量类型和复数类型的相互转换。,见教材,P155,19,【,例,10-13】,使用构造函数实现二维向量类型和复数类型的相互转换。,程序见教材,P157,20,10.9,类模板与模板类,在编写程序时,有许多类的工作机制是相同的,只是其使用的数据类型不同。链表就是一个较为典型的例子,可以有整型链表、结构链表或自定义类的链表,但就链表本身的操作来说是相同的。在链表操作时,如果能够把要处理的类型当作参数,就可以构建一个通用的链表类。,类模板的定义格式如下:,template class,类名,21,这里,template,是指出在所定义的类中,将使用到一个参数的类型为,T,;编译时,类型,T,将被调用时的具体类型替换,产生一个具体的类,称为模板类(由模板产生的类)。,来看一个具体的例子:单向链表,其结构图,6.1,所示。,这里的数据可以是任意类型的,而对于任一个单向链表,其操作都是相同的;单向链表都具有增加、删除、寻找、遍历等操作,链首指针,节点指针,数据,节点指针,数据,节点指针,数据,图,10.1,单向链表,22,【,例,10-14】,通用链表类的定义。,程序见教材,P159,23,本章小结,本章介绍了,C+,中,运算符重载和类型转换的概念,举例说明了运算符重载和类型转换的用法。,使用运算符重载可以使程序易于理解并易于对对象进行操作。几乎所有的,C+,运算符都可以被重载。,如果在类中没有说明本身的拷贝构造函数和赋值运算符,编译程序将会提供,但它们都只是对对象进行成员浅拷贝。,this,指针指向当前的对象,它是所有成员函数的不可见的参数,在重载运算符时,经常返回,this,指针的间接引用。,24,在实际应用中应注意以下几点:,设计和实现使用重载运算符,需要深入了解语言、运算符和类。合理地使用运算符重载,使它成为程序设计的有力工具。不要仅仅为了证明语言的威力而使用重载运算符。,不能改变运算符操作数的数量。,大多数运算符属于某个运算符系列。如果实现了系列中的某个成员,则需要实现其他的成员,(,以保持接口完整性和一致性,),。,任何不需要左值并具有交换性的运算符都最好作为非成员函数,(+,、,-,等,),实现。这允许编译器在参数不匹配的情况下对第,t,个参数进行转换。,任何需要左值的运算符最好作为成员函数实现。这明确说明它只能在现存的、可以修改的对象上调用。,25,通过转换运算符可以在表达式中使用不同类型的对象。转换运算符不遵从函数应有返回值类型的规定,没有返回值。,在前缀增量和后缀增量运算符定义中,,int,参数只是标志是前缀还是后缀,没有其他作用。,拷贝构造函数用已经存在的对象来创建一个相同类型的新对象,而赋值运算符把一个对象的成员变量赋予一个已经存在的同类对象的同名变量。,使用模板,可以避免重复编写具有相同功能只是类型不同的类或函数代码,提高代码的编写效率,简化程序编写。在编译时,,C+,采用代码复制技术,生成相应的模板类或模板函数,这种方式存在的缺点是容易造成代码的膨胀,因此,在编写类模板或函数模板时应尽量减少其代码量。,26,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 小学资料


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

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


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