一、运算符重载的概念二、禁止重载的运算符三、运算符重_第1页
一、运算符重载的概念二、禁止重载的运算符三、运算符重_第2页
一、运算符重载的概念二、禁止重载的运算符三、运算符重_第3页
一、运算符重载的概念二、禁止重载的运算符三、运算符重_第4页
一、运算符重载的概念二、禁止重载的运算符三、运算符重_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

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

文档简介

一、运算符重载的概念

二、禁止重载的运算符

三、运算符重载的规则

四、单目运算符函数

五、双目运算符函数第17章运算符重载1一、运算符重载的概念系统的运算符主要分两大种类:一是单目运算符,另一是双目运算符。用不属于字符集的@代表各种许可的运算符,运算符构成的表达式抽象的表现格式为:

1.@x2.x@yx和y是运算符关联的操作数,其原先可以出现的数据类型是算术类型以及相关的指针类型如char*,CType*等。仅当存在运算符函数,操作数x或y才可以是对象。能转换为运算符函数的普通函数或单参数的函数,此时称单目运算符函数;或双参数的函数,此时称双目运算符函数.2原来普通的双参数(非静态的成员函数隐含this参数)函数:intCType::Add(intk){returnn+k;}intSub(CTypea,intk){returna.n-k;}可以相应地改写为运算符函数(其中n是CType类的int型数据成员):intCType::operator+(intk){returnn+k;}intoperator-(CTypea,intk){returna.n-k;}关键字operator是实现普通函数转换为运算符函数的语法中介,operator@是运算符函数名。当@分别对应+-*/时加分别得到四个运算符函数,依次是operator+加号运算符函数、operator-减号运算符函数、operator*乘号运算符函数和operator/除号运算符函数。3运算符重载是简化对象运算的函数调用现象,通过定义函数名为operator@的运算符函数,有关对象的函数调用可以简化为x@y或@x隐含调用的替代形式。 运算符函数operator@可以存在多个版本,只要编译器根据名称细分的结果在函数调用点能够进行唯一的匹配。

例如:iostream类中operator<<左移运算符函数就存在多个版本。 名称为operator@的运算符函数可以是成员函数也可以是全局函数。基于解除私有封装的考虑,全局函数声明为类的友员函数。如果类只有公共成员,则无需声明为友员函数。作为非虚的成员运算符函数和全局运算符函数的重载在编译阶段完成函数调用的确定,virtual关键字可以修饰作为成员的运算符函数。4[例]普通函数和相应的运算符函数#include<stdio.h>structCType{intn;CType(intr=1){n=r;}intoperator+(intk){returnn+k;}intAdd(intk){returnn+k;}};intoperator-(intk,CTypea){returnk-a.n;}intSub(intk,CTypea){returnk-a.n;}voidmain(){ CTypea(0),b(-7); printf("%d,%d,%d;",a+1,a.operator+(1),a.Add(1));printf("%d,%d,%d\n",1-b,operator-(1,b),Sub(1,b));}//输出:1,1,1;8,8,85含对象的表达式a+1等价于显式调用a.operator+(1),a+1是CType::operator+(int)的隐含调用,隐含调用方便了对象的操作。类似地隐含调用1-b等价于operator-(1,b)的显式调用。1+a不同于a+1,1+a要求匹配operator+(int,CType)型的全局运算符函数,而b-1要求匹配operator-(CType,int)型的全局函数或CType::operator-(int)型的成员函数。由于上例题未提供相应的函数,1+a和b-1此情形下是错误的表达式。6二、禁止重载的运算符

只有区区五个运算符不可以赋予运算符的函数实现,它们是:

.

.*

::

sizeof

?:圆点访问成员运算符”.”,对象访问成员指针运算符”.*”,这两个运算符分别是箭头访问成员运算符->和对象指针访问成员指针运算符->*的翻版为对象访问成员保留一条安全的入口。作用域分别符::和sizeof运算符都是编译阶段发挥作用。sizeof运算符的入口参数本身可以是各种类型名。另一个是三目条件运算符?:,这个运算符本身是if~else嵌套结构的合理重载。7三、运算符重载的规则存在两种运算符函数的调用格式,一种是将运算符函数当作函数名为operator@的显式调用格式,另一种是隐含调用格式,最终编译器在内部转换为显式调用格式。操作数x,y是算术或指针类型,表达式x@y,@x是常规的算术或指针运算,不涉及运算符函数。x或y是对象,x@y隐含调用相应的双目运算符函数;x是对象,@x隐含调用相应的单目运算符函数;若不存在相应的运算符函数,隐含调用导致错误。对于一个特定的类,系统提供等号运算符函数operator=和取地址运算符函数operator&供程序调用,即对于该类的对象x,y可以进行运算:x=y,&x。8对于对象表达式的前台隐含操作,必须存在一个无歧义的运算符函数作为背景支持。如果无相应的运算符函数或类型转换函数,则有关对象的隐含调用导致错误。

例如:x+=y是毫无根基的运算,除非存在相关的operator+=运算符函数。语句[CType*p;]定义的指针p不是对象而是一个常规的指针,对于变量指针合适的运算符也可作用于对象之指针。 运算符始终遵循内部类型所规定的优先原则、结合性。即对于出现在表达式中的运算符函数隐含调用如x@y,@x,优先级高的运算符函数优先被编译器隐含调用,同等级别的运算符函数根据结合性进行分解处理。9非静态的成员运算符函数的第一个参量对应隐含this的当前类的类型。类型转换运算符、函数调用运算符()、数组下标索引运算符[]、箭头运算符->函数和等号运算符函数只作为非静态的成员函数,其余的运算符可以和operator紧贴在一起构成全局函数。等号运算符函数operator=不为派生类继承。

不能凭空捏造C++语言中子虚乌有的运算符如FORTRAN语句的乘幂运算符**。运算符函数不允许用户提交缺省的默认值,函数调用运算符operator()例外。

10双目或单目全局运算符函数形参类型至少存在一个用户声明的类型,枚举类只能有全局运算符函数。 例如对于类声明[structCType{};],CType或CType&是用户声明的类型。CType*类型为常规的指针类型,不用于构成运算符函数的对象类型。voidoperator*(CType&,int){}是正确的函数定义,而voidoperator-(CType*,int){}与voidoperator+(char,int){}是错误的。可以在声明的类上对运算符函数提交任意的语义实现。但出于与内置类型表达式的接口考虑,最好按照运算符固有含义进行运算符函数定义。11四、单目运算符函数单目运算符中存在格外的运算符,这就是成为C++由来的后置运算符。这个运算符从后面作用于操作数,其运算符重载有其特殊的格式。对于语句[CTypeobj;]定义的对象obj,单目运算符函数隐含调用的格式为@obj。

121.单目成员运算符函数声明时不带参量,编译器隐含补充this参量。声明格式为:

ret_typeoperator@();返回类型单目运算符函数名();在类外定义的格式为:

ret_typeCType::operator@(){语句序列;}

隐含调用@obj转换为显式调用obj.operator@()。非静态的单目成员运算符函数隐含的形参this在调用点由&obj赋予具体的值。132.单目全局运算符函数仅带一个用户声明的类型,声明格式为:

ret_typeoperator@(CType&r);

在实现文件的定义格式为:

ret_typeoperator@(CType&r){显含形参r的语句序列;}隐含调用@obj转换为显式调用operator@(obj)。单目全局运算符函数形参r在调用点由obj赋予具体的值,若需要访问CType类的私有成员则声明为该类的友元函数。 @()成员版本也可调用operator@(obj)全局版本。为避免重载的歧义性,只提交一种版本,或者是成员版本,或者是全局版本。14[例]重载逻辑非运算符!负号运算符-和前置运算符++

staticintm=1;#include<stdio.h>classCType{intn;friendCType&operator++(CType&q);friendvoidmain();friendCTypeoperator-(constCType&r);public:CType(intr){n=r;}intoperator!();};

intCType::operator!(){printf("%d!,",m++);return!n;}15 CTypeoperator-(constCType&r){printf("%d-,",m++);returnCType(-r.n);}CType&operator++(CType&q){printf("%d++,",m++);++q.n;returnq;}voidmain(){ CTypea(2),b(-1); a=!-++b;printf("a=%d\n",a.n);a=(operator-(operator++(b))).operator!(); printf("a=%d",a.n);}//a=1先调用构造函数CType(int)即a=1相当于a=CType(1)++b等价于operator++(b),-++b等价于operator-(operator++(b))等。16五、双目运算符函数

双目运算符函数如果是非静态的成员函数则声明的时候仅带一个参量,编译器隐含的补充一个this参量。如果声明为全局函数,则双目运算符函数带两个参量,其中一个参量的类型必须是一个用户声明的类型。

171.双目成员运算符函数 作为成员的双目运算符函数的声明格式为:

ret_typeoperator@(type);返回类型双目运算符函数名(数据类型);在类外定义的格式为:

ret_typeCType::operator@(typearg){语句序列;}对于定义语句[CTypeobj;]设定的对象obj和type型表达式var,隐含调用的格式为:

obj@var隐含调用obj@var转换为obj.operator@(var)的显式调用形式。非静态的双目成员运算符函数隐含的形参this在调用点由&obj赋予具体的值,实参var负责形参arg的初始化。182.双目全局运算符函数 双目全局运算符函数由于接口的需要花样增多一倍,相应的声明格式为:

ret_typeoperator@(CType&r,typearg);

//此格式可以从成员版本变换而来返回类型双目运算符函数名(当前类名,其它类名);

ret_typeoperator@(typearg,CType&r);返回类型双目运算符函数名(其它类名,当前类名);相应的隐含调用的格式为:

obj@varvar@obj19obj@var转换为显式调用operator@(obj,var)即启动operator@(CType&r,typearg)函数,var@obj转换为显式调用operator@(var,obj)即启动operator@(typearg,CType&r)函数,形参r由对象名obj初始化,实参var赋予形参arg具体的初值。 @(var)也可调用全局版本operator@(obj,var)。两者本质上应是等价的,因此酌情提交一个版本,以免导致歧义。20[例]重载加减乘除运算符实现结构变量的四则运算#include<stdio.h>structCA{CAoperator+(CAb);CA(intr=1){n=r;};intn;};staticintm=1;CACA::operator+(CAa){printf("%d+,",m++);returnCA(n+a.n);}CAoperator-(CAa,constCA&r){printf("%d-,",m++);returnCA(a.n-r.n);}CAoperator*(CAa,CAb){printf("%d*,",m++);returnCA(a.n*b.n);}CAoperator/(constCA&r,constCA&q){printf("%d/,",m++);returnCA(r.n/q.n);}21voidmain(){ CAa,b(2),c(6);a=(a+b)*(c/b)-b;printf("a=%d;",a.n);a=operator-((operator*(a.operator+(b),operator/(c,b))),b);printf("a=%d;",a.n);}

//输出:1/,2+,3*,4-,a=7;5/,6+,7*,8-,a=25;

22对于对象的引用返回,引用是已经建立的对象的别名,返回的是不独立的对象,此时编译器不需要额外建立临时对象。对于对象的数值返回,返回一个局部或临时的独立对象,输送给主控

温馨提示

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

评论

0/150

提交评论