版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1第十章 运算符重载与类模板2理解为什么要进行运算符重载,在什么情况下要进行运算符重载掌握通过成员函数重载运算符,借助友元函数实现运算符重载理解引用在运算符重载中的作用,引用作为参数和返回值的好处和用法理解类型转换的必要性,能够在程序设计中正确应用类型转换理解为什么要引入类模板的概念,掌握类模板的应用310.1.1 10.1.1 运算符重载的例子运算符重载的例子在程序中,经常会使用运算符,但在程序中,经常会使用运算符,但C+C+中已经定义的中已经定义的运算符都是针对基本数据类型的,那么能否将它们用于复运算符都是针对基本数据类型的,那么能否将它们用于复杂的类对象呢?在学习本章之前,我们往往是编写
2、实现相杂的类对象呢?在学习本章之前,我们往往是编写实现相应运算功能的函数来解决复杂类型的运算问题。首先来看应运算功能的函数来解决复杂类型的运算问题。首先来看一个复数加法运算的例子,请注意程序中,加法运算时表一个复数加法运算的例子,请注意程序中,加法运算时表达式的书写形式。达式的书写形式。【例例6-16-1】复数的加运算。见教材复数的加运算。见教材P133P1334程序说明:程序说明:在在【例例10-110-1】为了解决复数的存储问题,在复数类为了解决复数的存储问题,在复数类ComplexComplex中,定义了两个私有成员变量:中,定义了两个私有成员变量:realreal(复数的实(复数的实部
3、)和部)和imagimag(复数的虚部);并定义了公有的复数加法函(复数的虚部);并定义了公有的复数加法函数数add()add()和友元输出函数和友元输出函数print()print()显示复数。在显示复数。在mainmain函数中函数中定义了三个复数对象,使用加法函数定义了三个复数对象,使用加法函数addadd进行进行3 3个复数的相个复数的相加,并输出结果。加,并输出结果。在程序中三个复数相加的表达式为:在程序中三个复数相加的表达式为:c4 = c1.add(c2).add(c3);c4 = c1.add(c2).add(c3);用这种方式书写表达式,不仅形式复杂、不符合人们用这种方式书写
4、表达式,不仅形式复杂、不符合人们的日常书写习惯,而且不易理解;复数的运算越复杂,书的日常书写习惯,而且不易理解;复数的运算越复杂,书写的表达式越困难,给使用自定义类编写程序带来诸多不写的表达式越困难,给使用自定义类编写程序带来诸多不便。如果能够像使用基本类型那样用运算符来书写复数运便。如果能够像使用基本类型那样用运算符来书写复数运算表达式(如算表达式(如c4 = c1+c2+c3;c4 = c1+c2+c3;),不仅书写简单,也更容),不仅书写简单,也更容易理解;这正是在易理解;这正是在C+C+中引入了运算符重载的意义所在。中引入了运算符重载的意义所在。下面通过使用运算符重载进行复数加运算例子
5、来了解如何下面通过使用运算符重载进行复数加运算例子来了解如何进行运算符的重载。进行运算符的重载。5见教材见教材P134P134输出结果:输出结果: 11+2i11+2i程序说明:程序说明:该程序的作用和该程序的作用和【例例10-110-1】相同,只是用运算符重载函数相同,只是用运算符重载函数代替了加法函数。代替了加法函数。比较两个程序不难发现,比较两个程序不难发现,【例例10-210-2】中书写的复数相加表中书写的复数相加表达式,含义清晰,便于书写。让复数类的使用变得更加简易。达式,含义清晰,便于书写。让复数类的使用变得更加简易。程序中程序中“+”+”运算符重载的定义如下:运算符重载的定义如下
6、:Complex operator +(Complex & c);Complex operator +(Complex & c);它与一般函数的定义非常相似,不同的是运算符重载函数它与一般函数的定义非常相似,不同的是运算符重载函数的名字(的名字(“operator +”operator +”)是由)是由“operator”operator”关键字和紧随其关键字和紧随其后的运算符后的运算符“+”+”组成;关键字组成;关键字“operator”operator”表明该函数是一表明该函数是一个运算符重载函数。在个运算符重载函数。在【例例10-210-2】中,该函数是作为类中,该函数是
7、作为类ComplexComplex的成员函数,因此把以这种方式的运算符重载称作重的成员函数,因此把以这种方式的运算符重载称作重载为类运算符。载为类运算符。6见教材见教材P136P136输出结果:输出结果:11+2i11+2i程序说明:程序说明:本例实现的功能与本例实现的功能与【例例10-110-1】和和【例例10-210-2】完全相同。完全相同。本例中,本例中,“+”+”运算符重载函数的定义如下:运算符重载函数的定义如下:Complex operator +(Complex & c1,Complex & c2);Complex operator +(Complex &
8、c1,Complex & c2);由于该函数是一般的普通函数,不是类的成员函数,只是由于该函数是一般的普通函数,不是类的成员函数,只是为能够访问类的私有数据成员,而把其声明为类的友元函为能够访问类的私有数据成员,而把其声明为类的友元函数,因此在定义时参数表中必须指定两个参数:第数,因此在定义时参数表中必须指定两个参数:第1 1个参数个参数作为运算符的左操作数,第作为运算符的左操作数,第2 2参数作为运算符的右操作数。参数作为运算符的右操作数。7C+C+对运算符重载作出了一定的限制和规定,在重载运算符时,需要对运算符重载作出了一定的限制和规定,在重载运算符时,需要注意以下几点:注意以下几
9、点:不是所有运算符都可以被重载。不是所有运算符都可以被重载。C+C+的大部分运算符都可以被重载。可以重载的运算符如下:的大部分运算符都可以被重载。可以重载的运算符如下: new new delete delete new new delete delete + - + - * * / % & / % & | = += -=| = += -=* *- /= %= = &= |= - /= %= = &= |= & | + - - & | + - -* * - - () () 其中,运算符其中,运算符()()是函数调用运算符,是函数调用运算符,是下标
10、运算符。是下标运算符。+ +、- -、* * 和和 & & 的一元、二元形式都可以被重载。自增运算符的一元、二元形式都可以被重载。自增运算符 + + 和自减运算符和自减运算符 - - 的前置、后置形式都可以被重载。的前置、后置形式都可以被重载。以上可重载运算符中,除了赋值运算符以上可重载运算符中,除了赋值运算符=之外,基类中所有被重载之外,基类中所有被重载的运算符都将被派生类继承。的运算符都将被派生类继承。8不可以重载的运算符如下:不可以重载的运算符如下:.(.(成员运算符成员运算符) .) .* * ( (成员对象选择符成员对象选择符) : () : (解析运算解析运算符符)
11、 ) ?: : (条件运算符)(条件运算符)重载不能改变运算符的优先级。重载不能改变运算符的优先级。假定已定义了复数类假定已定义了复数类Complex, Complex, 并且已定义了加法和乘法并且已定义了加法和乘法运算符重载函数,运算符重载函数,Complex c1(1, 2), c2(3, 4), c3(5, 6), answer;Complex c1(1, 2), c2(3, 4), c3(5, 6), answer;answer = c1 + c2 answer = c1 + c2 * * c3; c3;在这个表达式中,乘法运算优先级高于加法运算,它等效在这个表达式中,乘法运算优先级高
12、于加法运算,它等效于于answer = c1 + (c2 answer = c1 + (c2 * * c3); c3);如同系统定义数据类型一样如同系统定义数据类型一样, ,可以使用括号强制改变重载可以使用括号强制改变重载运算符的计算顺序,例如:运算符的计算顺序,例如:answer = (c1 + c2) answer = (c1 + c2) * * c3; c3;重载不能改变运算符的结合律。重载不能改变运算符的结合律。9重载不能改变运算符的操作数个数。重载不能改变运算符的操作数个数。重载的一元运算符仍然是一元运算符,重载的二元运算符仍然是重载的一元运算符仍然是一元运算符,重载的二元运算符仍然
13、是二元运算符。二元运算符。C+C+中唯一的三元运算符(?:)不能被重载。中唯一的三元运算符(?:)不能被重载。运算符运算符 + +、- -、* *、& & 和和 既可以用作一元运算符和二元运算既可以用作一元运算符和二元运算符,对这几个运算符,要分别把他们重载为一元运算符和二元符,对这几个运算符,要分别把他们重载为一元运算符和二元运算符。运算符。不能创建新的运算符,只有现用的运算符才能被重载。不能创建新的运算符,只有现用的运算符才能被重载。运算符重载函数的参数至少有一个必须是类的对象或者是类的运算符重载函数的参数至少有一个必须是类的对象或者是类的对象的引用。对象的引用。运算符只能
14、被显式重载(不存在隐式重载),例如,运算符运算符只能被显式重载(不存在隐式重载),例如,运算符+和和=已被分别重载,这不意味着运算符已被分别重载,这不意味着运算符+=+=或或= = =已被已被重载。重载。运算符重载函数不能带有缺省参数。运算符重载函数不能带有缺省参数。重载运算符时,要保持语义上的一致性。例如,重载运算符重载运算符时,要保持语义上的一致性。例如,重载运算符+时,仍应对有关对象执行加法运算。当然,也可以定义为时,仍应对有关对象执行加法运算。当然,也可以定义为其它某种运算,但这样做既没有必要,也容易造成混乱。其它某种运算,但这样做既没有必要,也容易造成混乱。C+C+规定,规定,“=
15、=、() ()、 、-”四种运算符必须重载为类运算符。四种运算符必须重载为类运算符。10对名为对名为T T的类,其赋值运算符重载函数的格式如下:的类,其赋值运算符重载函数的格式如下:T operator =(T &);T operator =(T &);由于赋值运算符只能重载为类运算符,所以这是赋值运算由于赋值运算符只能重载为类运算符,所以这是赋值运算符重载函数的唯一格式。符重载函数的唯一格式。对名为对名为T T的类,其二元运算符(用的类,其二元运算符(用# #表示)重载函数的格表示)重载函数的格式如下:式如下:T operator #(T &); /T operato
16、r #(T &); /重载为类成员运算符重载为类成员运算符或或T operatore #(T &,T &); /T operatore #(T &,T &); /重载为非类成员运算符重载为非类成员运算符四则运算符属于二元运算符,也可以使用这两种形式。四则运算符属于二元运算符,也可以使用这两种形式。下面仍以复数运算为例,说明赋值运算符和四则运算符的下面仍以复数运算为例,说明赋值运算符和四则运算符的重载。重载。【例例10-410-4】复数的四则运算复数的四则运算 见教材见教材P138P13811自增自增1 1运算符运算符“+”和自减和自减1 1运算符运算符“
17、-”都各有两种形式:前缀(前都各有两种形式:前缀(前运算)和后缀(后运算)。例如,运算)和后缀(后运算)。例如,+a+a是前运算符:在进行其他运是前运算符:在进行其他运算前,变量算前,变量a a首先增首先增1 1。a+a+是后运算符:做完其他运算后,是后运算符:做完其他运算后,a a才增才增1 1。这四种形式的每一种都可以重载。这四种形式的每一种都可以重载。增增1 1运算符和减运算符和减1 1运算符都只有一个操作数,通常被重载为类运算符。运算符都只有一个操作数,通常被重载为类运算符。一元类运算符重载函数的参数表理应没有参数(操作数即是类对象本一元类运算符重载函数的参数表理应没有参数(操作数即是
18、类对象本身),但为了区分前运算和后运算这两种形式,身),但为了区分前运算和后运算这两种形式,C+C+中规定:中规定:前运算符重载函数的参数表没有参数;前运算符重载函数的参数表没有参数;后运算符重载函数的参数表设一个整数参数,这个参数称为哑元,只后运算符重载函数的参数表设一个整数参数,这个参数称为哑元,只作为一个标志,用以区别前运算符。作为一个标志,用以区别前运算符。所以,对名为所以,对名为T T的类,重载前运算符和后运算符的函数原型取如下格的类,重载前运算符和后运算符的函数原型取如下格式:式:T operator +(); /T operator +(); /重载前增重载前增1 1运算符运算符
19、T operator +(int); /T operator +(int); /重载后增重载后增1 1运算符运算符T operator -(); /T operator -(); /重载前减重载前减1 1运算符运算符T operator -(int); /T operator -(int); /重载后减重载后减1 1运算符运算符为了说明增为了说明增1 1运算符和减运算符和减1 1运算符重载,下面给出一个分数类作自增,运算符重载,下面给出一个分数类作自增,自减的例子。自减的例子。【例例6-56-5】分数类的自增,自减。分数类的自增,自减。 见教材见教材P142P14212在在C+C+中对于使用内
20、部数据类型定义的变量,可以使用中对于使用内部数据类型定义的变量,可以使用六个关系运算符六个关系运算符“ 、=、 = = = = 和和 !=!=”进行进行比较运算。而要对自定义类定义的变量进行比较运算,用比较运算。而要对自定义类定义的变量进行比较运算,用户就必须重载这些运算符。户就必须重载这些运算符。下面以分数的下面以分数的 为例说明关系运算符的重载。为例说明关系运算符的重载。【例例10-610-6】比较两个分数大小,输出值大的分数。见教比较两个分数大小,输出值大的分数。见教材材P144P14413在在C+C+中允许把算术运算符和赋值运算符组合在一起使用,中允许把算术运算符和赋值运算符组合在一起
21、使用,这种书写方法简洁高效;同样也可以在自定义类型中重载这种书写方法简洁高效;同样也可以在自定义类型中重载这些运算符。为了简单起见,仍然使用分数的例子。这些运算符。为了简单起见,仍然使用分数的例子。【例例10-710-7】分数的加法运算。见教材分数的加法运算。见教材P145P14514“”“”下标运算符通常用于数组,下标运算符通常用于数组,c+c+也允许重载这个运也允许重载这个运算符,在重载这个运算符时,需要注意的是:当算符,在重载这个运算符时,需要注意的是:当“”运运算符位于算符位于“=”=”左边时,是修改数组中元素的值,需要返左边时,是修改数组中元素的值,需要返回这个元素的指针或引用;当回
22、这个元素的指针或引用;当“”运算符位于运算符位于“=”=”右右边时,是取得数组中元素的值,需要返回这个元素的值或边时,是取得数组中元素的值,需要返回这个元素的值或引用;为了能使引用;为了能使“”运算符即可用于运算符即可用于“=”=”左边,也可左边,也可用于用于“=”=”右边,在重载右边,在重载“”运算符时,必须返回该元运算符时,必须返回该元素的引用。素的引用。下面给出一个数组类的例子来说明这一问题。下面给出一个数组类的例子来说明这一问题。【例例10-810-8】一个数组类的例子。见教材一个数组类的例子。见教材P147P1471510.7.1 10.7.1 插入运算符的重载插入运算符的重载C+C
23、+中对左移运算符中对左移运算符 “” ” 进行重载,以便输出进行重载,以便输出C+C+内部类型的数据。对于自定义类型也可以重载运算符内部类型的数据。对于自定义类型也可以重载运算符 “”进行重载,以便把外来的信息输入进行重载,以便把外来的信息输入到所有的到所有的C+C+内部数据类型的变量,这些重载函数作为系统类内部数据类型的变量,这些重载函数作为系统类的成员函数。例如,如果的成员函数。例如,如果i i是一个整型变量,是一个整型变量,C+C+便将输入语便将输入语句句cini;cini;翻译为翻译为cin.operator(i);cin.operator(i);然后调用此函数,读取一然后调用此函数,
24、读取一个值,存入变量个值,存入变量i i中。中。为了支持自定义类型,用户应重载输入运算符为了支持自定义类型,用户应重载输入运算符“”。在重载。在重载时,如果作为一般的函数来定义(而非类的成员函数),则这时,如果作为一般的函数来定义(而非类的成员函数),则这个重载运算符在被使用时应被声明为类的友元运算符。因为个重载运算符在被使用时应被声明为类的友元运算符。因为“”的第一个操作数是系统类的对象的第一个操作数是系统类的对象cincin(系统类(系统类iostreamiostream的对象),因此,作为友元函数,类的对象),因此,作为友元函数,类X X的输入运算符重载函数的输入运算符重载函数的原型应为
25、:的原型应为:istream & operator (istream &, X &);istream & operator (istream &, X &);请注意:这个函数的第一个参数是输入流的引用,第二个参数请注意:这个函数的第一个参数是输入流的引用,第二个参数是类是类X X的引用。函数返回输入流的引用,其目的是为了能连续的引用。函数返回输入流的引用,其目的是为了能连续输入。对此,可以仿照输入。对此,可以仿照6.7.16.7.1节做出解释。节做出解释。【例例10-1010-10】分数的输入。见教材分数的输入。见教材P151P15117在在C+
26、C+中,当使用数值类型进行计算时,各种类型之中,当使用数值类型进行计算时,各种类型之间可以隐式或强制转换;例如:间可以隐式或强制转换;例如:double d;double d;int a = 2;int a = 2;d = a + 5.3;d = a + 5.3;这种书写方式,使代码看起来优雅而自然。在用户自这种书写方式,使代码看起来优雅而自然。在用户自定义类中,没有进行类似的定义而无法使用这种方法。定义类中,没有进行类似的定义而无法使用这种方法。 18在定义了类型转换后,对所有在定义了类型转换后,对所有TRangeIntTRangeInt类型变量的计算类型变量的计算都可以先转换成都可以先转换
27、成intint类型,再进行计算,因此,可以不需类型,再进行计算,因此,可以不需要进行运算符的重载(如下面例子中的要进行运算符的重载(如下面例子中的“+ +”、“- -”运算运算符)。符)。【例例10-1110-11】TRangeIntTRangeInt类型的加、减运算。类型的加、减运算。 见教材见教材P154P15419有两种方法可以实现自定义类型之间的转换:使用类型转有两种方法可以实现自定义类型之间的转换:使用类型转换符函数和构造函数。不仅可以在基本类型转换和自定义换符函数和构造函数。不仅可以在基本类型转换和自定义类型之间实现类型的转换,也可以在两个自定义类型之间类型之间实现类型的转换,也可
28、以在两个自定义类型之间实现。实现。【例例10-1210-12】使用类型转换符函数实现二维向量类型和复使用类型转换符函数实现二维向量类型和复数类型的相互转换。数类型的相互转换。见教材见教材P155P15520程序见教材P15721在编写程序时,有许多类的工作机制是相同的,只是其使在编写程序时,有许多类的工作机制是相同的,只是其使用的数据类型不同。链表就是一个较为典型的例子,可以用的数据类型不同。链表就是一个较为典型的例子,可以有整型链表、结构链表或自定义类的链表,但就链表本身有整型链表、结构链表或自定义类的链表,但就链表本身的操作来说是相同的。在链表操作时,如果能够把要处理的操作来说是相同的。在
29、链表操作时,如果能够把要处理的类型当作参数,就可以构建一个通用的链表类。的类型当作参数,就可以构建一个通用的链表类。类模板的定义格式如下:类模板的定义格式如下:template class template class 类名类名 22这里这里templatetemplate是指出在所定义的类中,将使用到一是指出在所定义的类中,将使用到一个参数的类型为个参数的类型为T T;编译时,类型;编译时,类型T T将被调用时的具体类型替换,将被调用时的具体类型替换,产生一个具体的类,称为模板类(由模板产生的类)。产生一个具体的类,称为模板类(由模板产生的类)。来看一个具体的例子:单向链表,其结构图来看一个
30、具体的例子:单向链表,其结构图6.16.1所示。所示。这里的数据可以是任意类型的,而对于任一个单向链表,其操这里的数据可以是任意类型的,而对于任一个单向链表,其操作都是相同的;单向链表都具有增加、删除、寻找、遍历等操作都是相同的;单向链表都具有增加、删除、寻找、遍历等操作作 链首指针节点指针数据节点指针数据节点指针数据图10.1单向链表23程序见教材P15924本章介绍了C+中,运算符重载和类型转换的概念,举例说明了运算符重载和类型转换的用法。使用运算符重载可以使程序易于理解并易于对对象进行操作。几乎所有的C+运算符都可以被重载。如果在类中没有说明本身的拷贝构造函数和赋值运算符,编译程序将会提供,但它们都只是对对象进行成员浅拷贝。this指针指向当前的对象,它是所有成员函数的不可见的参数,在重载运算符时,经常返回this指针的间接引用。25在实际应用中应注意以下几点:在实际应用中应注意以下几点:设计和实现使用重载运算符,需要深入了解语言、运算设计和实现使用重载运算符,需要深入了解语言、运算符和类。合
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 孝感学院电路试题及答案
- 家电行业深度研究报告:国补政策延续2026年内需压力可控
- 药食同源:中国传统药膳的文化智慧与现代传承
- AI赋能宠物医疗:疾病诊断技术应用与实践指南
- 精准诊断细菌性食物中毒的新型分子检测方法
- 《海鸥乔纳森》读后感(15篇)
- 系统高可用性扩展
- 2025-2030智慧农业设备系统市场现状需求分析投资评估未来发展趋势规划报告
- 2025-2030智慧农业行业市场供需分析及投资前景规划研究文档
- 2025-2030智慧农业无人机行业市场环境供需评估投资评估发展规划分析研究报告
- 《中国帕金森病诊疗指南(第四版)》(2023)要点
- 婚礼上女方家长的精彩讲话稿7篇
- 烟花爆竹储存培训课件
- 抗挫折能力课件(修改)
- 南通市海门区国有企业招聘考试真题2022
- 2023年钻井液液气分离器安装与使用规范
- 陕西境某段高速公路建设工程地质灾害危险性评估报告报告
- GB/T 8237-2005纤维增强塑料用液体不饱和聚酯树脂
- GB/T 3047.2-1992高度进制为44.45mm的面板、机架和机柜的基本尺寸系列
- GB/T 12719-2021矿区水文地质工程地质勘查规范
- GB 35574-2017热电联产单位产品能源消耗限额
评论
0/150
提交评论