数据结构-运算符重载.ppt_第1页
数据结构-运算符重载.ppt_第2页
数据结构-运算符重载.ppt_第3页
数据结构-运算符重载.ppt_第4页
数据结构-运算符重载.ppt_第5页
已阅读5页,还剩70页未读 继续免费阅读

下载本文档

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

文档简介

第10章运算符重载 10 1什么是运算符重载10 2运算符重载的方法10 3重载运算符的规则10 4运算符重载函数作为类成员函数和友元函数10 5重载双目运算符10 6重载单目运算符10 7重载流插入运算符和流提取运算符10 8不同类型数据间的转换 10 1什么是运算符重载 C 中预定义的运算符的操作对象只能是基本数据类型 但实际上 对于许多用户自定义的类型 也需要类似的运算 这时就必须重新定义这些运算符 赋于已有运算符新的功能 使之能够用于特定类型执行特定操作 实际上 很多C 操作符已经被重载 例如 将 操作符用于地址 将得到在这个地址中的值 但将它用于两个数字时 得到的将是它们的乘积 C 根据操作数的数目和类型来决定采用哪种操作 使同一个运算符作用于不同类型的数据时导致不同的行为的这种机制称为运算符重载 C 通过重载运算符使之用于自定义类型 扩展了运算符的功能 这也是C 最具吸引力的优点之一 运算符重载机制 运算符重载是通过重载一种特殊函数 运算符函数来实现的 对C 运算符可作如下理解 编译器在对运算符进行编译处理时 将一个运算符编译成如下形式 一元运算符 obj operator obj 二元运算符 obj1 obj2 operator obj1 obj2 由于C 中有前增 减 后增 减 为了区分它们 C 将后增 减 编译成 后增 obj operator obj 0 后减 obj operator obj 0 依照上述规则 8 9 10 5 3 5分别编译成运算符函数调用形式为 operator 8 9 operator 10 5 3 5 C 为 运算符提供了多种运算符函数 其原型有 operator int int operator double double 等 10 2运算符重载的方法 运算符重载的方法是定义一个重载运算符的函数 在需要执行被重载的运算符时 系统就自动调用该函数 以实现相应的运算 也就是说 运算符重载是通过定义函数实现的 运算符重载实质上是函数的重载 重载运算符的函数一般格式如下 函数类型operator运算符名称 形参表列 对运算符的重载处理 includeusingnamespacestd classComplex doublereal doubleimag public Complex real 0 imag 0 Complex doubler doublei real r imag i friendComplexoperator Complex Complexoperator Complex intmain Complexc1 3 4 c2 5 10 c3 c3 c1 c2 cout c1 c1 display cout c2 c2 display cout c1 c2 c3 display return0 10 3重载运算符的规则 C 不允许用户自己定义新的运算符 只能对已有的C 运算符进行重载 C 允许重载的运算符C 中绝大部分的运算符允许重载 具体规定见书中表10 1 不能重载的运算符只有5个 成员访问运算符 成员指针访问运算符 域运算符 sizeof 长度运算符 条件运算符 前两个运算符不能重载是为了保证访问成员的功能不能被改变 域运算符和sizeof运算符的运算对象是类型而不是变量或一般表达式 不具重载的特征 重载不能改变运算符运算对象 即操作数 的个数 重载不能改变运算符的优先级别 重载不能改变运算符的结合性 重载运算符的函数不能有默认的参数 否则就改变了运算符参数的个数 与前面第 3 点矛盾 重载的运算符必须和用户定义的自定义类型的对象一起使用 其参数至少应有一个是类对象 或类对象的引用 也就是说 参数不能全部是C 的标准类型 以防止用户修改用于标准类型数据的运算符的性质 用于类对象的运算符一般必须重载 但有两个例外 运算符 和 不必用户重载 赋值运算符 可以用于每一个类对象 可以利用它在同类对象之间相互赋值 地址运算符 也不必重载 它能返回类对象在内存中的起始地址 应当使重载运算符的功能类似于该运算符作用于标准类型数据时所实现的功能 运算符重载并不能自动实现 必须编写运算符重载函数才能实现 有时这此函数最好作为成员函数出现 有时它们最好是友元函数 偶尔它们可以作为全局 非友元函数出现 10 4运算符重载函数作为类成员函数和友元函数 在上节中采用友元的形式重载了复数 的运算符 其声明如下 friendComplexoperator Complex现将之改为成员函数的形式 classComplex private doublereal doubleimag public Complex real 0 imag 0 Complex doubler doublei real r imag i Complexoperator Complex ComplexComplex operator Complex 是双目运算符 为什么程序中的重载函数中只有一个参数呢 实际上 运算符重载函数有两个参数 由于重载函数是Complex类中的成员函数 有一个参数是隐含的 这个隐含的参数就是this指针 在重载运算符为成员函数时 其第一个参数隐含地为左操作数对象 Complexc1 3 4 c2 5 10 c3 c3 c1 c2 实际上执行的是c1 operator this c2 下面这些Complex成员函数声明正确吗 Complexoperator Complexc1 Complexc2 Complexoperator inta 如要能进行如下运算 重载的操作符可以定义为成员函数吗 2 a a为复数对象 如果左操作数必须是一个不同类的对象或者是一个基本类型对象 那么该运算符函数必须作为全局函数来实现 如果要重载 运算符 运算符重载函数必须为类的成员函数 为什么 10 5重载双目运算符 双目运算符 或称二元运算符 是C 中最常用的运算符 双目运算符有两个操作数 通常在运算符的左右两侧 如3 5 a b i 10等 在重载双目运算符时 不言而喻在函数中应该有两个参数 下面再举一个例子说明重载双目运算符的应用 例 定义一个字符串类String 用来存放不定长的字符串 重载运算符 用于两个字符串的等于 小于和大于的比较运算 下面分几步来介绍编程过程 先建立一个String类 includeusingnamespacestd classString public String p NULL 默认构造函数 String char str 构造函数voiddisplay private char p 字符型指针 用于指向字符串 String String char str 定义构造函数 p str 使p指向实参字符串 voidString display 输出p所指向的字符串 cout p intmain Stringstring1 Hello string2 Book string1 display cout endl string2 display return0 2 增加对运算符重载的部分 先重载一个运算符 include includeusingnamespacestd classString public String p NULL 默认构造函数 String char str 构造函数voiddisplay friendbooloperator String String String char str 定义构造函数 p str 使p指向实参字符串 voidString display 输出p所指向的字符串 cout String intmain Stringstring1 Hello string2 Book coutstring2 endl 程序运行结果为1 其他两个运算符的重载如法炮制即可 扩展到对3个运算符重载 见教材P325通过这个例子 不仅可以学习到有关双目运算符重载的知识 而且还可以学习怎样去编写C 程序 这种方法的指导思想是 先搭框架 逐步扩充 由简到繁 最后完善 边编程 边调试 边扩充 千万不要企图在一开始时就解决所有的细节 类是可扩充的 可以一步一步地扩充它的功能 最好直接在计算机上写程序 每一步都要上机调试 调试通过了前面一步再做下一步 步步为营 10 6重载单目运算符 单目运算符只有一个操作数 如 a b c p 还有最常用的 i和 i等 重载单目运算符的方法与重载双目运算符的方法是类似的 但由于单目运算符只有一个操作数 因此运算符重载函数只有一个参数 单目运算符一般重载为成员函数 例 有一个Time类 包含数据成员minute 分 和sec 秒 模拟秒表 每次走一秒 满60秒进一分钟 此时秒又从0开始算 要求输出分和秒的值 includeusingnamespacestd classTime public Time minute 0 默认构造函数sec 0 Time intm ints minute m sec s 构造函数重载Timeoperator 声明运算符重载函数voiddisplay cout minute sec endl 定义输出时间函数 private intminute intsec TimeTime operator 定义运算符重载函数 if sec 60 sec 60 满60秒进1分钟 minute return this 返回当前对象值 intmain Timetime1 34 0 for inti 0 i 61 i time1 time1 display return0 和 运算符有两种使用方式 前置自增运算符和后置自增运算符 它们的作用是不一样的 在重载时怎样区别这二者呢 针对 和 这一特点 C 约定 在自增 自减 运算符重载函数中 增加一个int型形参 就是后置自增 自减 运算符函数 例 在上例程序的基础上增加对后置自增运算符的重载 修改后的程序如下 classTime public Time minute 0 默认构造函数sec 0 Time intm ints minute m sec s 构造函数重载Timeoperator 声明前置自增运算符 重载函数Timeoperator int 声明后置自增运算符 重载函数voiddisplay cout minute sec endl 定义输出时间函数 private intminute intsec TimeTime operator if sec 60 sec 60 minute return this TimeTime operator int Timetemp this sec if sec 60 sec 60 minute returntemp 返回的是自加前的对象 可以看到 重载后置自增运算符时 多了一个int型的参数 增加这个参数只是为了与前置自增运算符重载函数有所区别 此外没有任何作用 编译系统在遇到重载后置自增运算符时 会自动调用此函数 intmain Timetime1 34 59 time2 cout time1 time1 display time1 cout time1 time1 display time2 time1 cout time1 time1 display cout time2 time2 display 10 7重载流插入运算符和流提取运算符 C 的流插入运算符 是C 在类库中提供的 所有C 编译系统都在类库中提供输入流类istream和输出流类ostream cin和cout分别是istream类和ostream类的对象 在类库提供的头文件中已经对 进行了重载 使之作为流插入运算符和流提取运算符 能用来输出和输入C 标准类型的数据 因此 凡是用 cout 对标准类型数据进行输入输出的 都要用 include把头文件包含到本程序文件中 用户自己定义类型的数据 是不能直接用 来输出和输入的 如果想用它们输出和输入自己声明的类型的数据 必须对它们重载 对 重载的函数形式如下 istream重载运算符 的函数的第一个参数和函数的类型都必须是istream 类型 第二个参数是要进行输入操作的类 重载 和 的函数作为友元函数或普通的函数 而不能将它们定义为成员函数 10 7 1重载流插入运算符 例用重载的 输出复数 classComplex public Complex real 0 imag 0 Complex doubler doublei real r imag i Complexoperator Complex ComplexComplex operator Complex 请思考 returnoutput的作用是什么 intmain Complexc1 2 4 c2 6 10 c3 c3 c1 c2 cout c3 return0 10 7 2重载流提取运算符 C 预定义的运算符 的作用是从一个输入流中提取数据 如 cin i 表示从输入流中提取一个整数赋给变量i 假设已定义i为int型 重载流提取运算符的目的是希望将 用于输入自定义类型的对象的信息 classComplex public Complex real 0 imag 0 Complex doubler doublei real r imag i Complexoperator Complex ComplexComplex operator Complex istream intmain Complexc1 c2 cin c1 c2 cout c1 c1 endl cout c2 c2 endl return0 10 8不同类型数据间的转换10 8 1标准类型数据间的转换 在C 中 某些不同类型数据之间可以自动转换 例如inti 6 i 7 5 i 编译系统对7 5是作为double型数处理的 在求解表达式时 先将6转换成double型 然后与7 5相加 得到和为13 5 在向整型变量i赋值时 将13 5转换为整数13 然后赋给i 这种转换是由C 编译系统自动完成的 用户不需干预 这种转换称为隐式类型转换 C 还提供显式类型转换 程序人员在程序中指定将一种指定的数据转换成另一指定的类型 其形式为类型名 数据 如int 89 5 其作用是将89 5转换为整型数89 对于用户自己声明的类型 编译系统并不知道怎样进行转换 解决这个问题的关键是让编译系统知道怎样去进行这些转换 需要定义专门的函数来处理 10 8 2转换构造函数 转换构造函数的作用是将一个其他类型的数据转换成一个类的对象 先回顾一下以前学习过的几种构造函数 默认构造函数 以Complex类为例 函数原型的形式为Complex 没有参数用于初始化的构造函数 函数原型的形式为Complex doubler doublei 形参表列中一般有两个以上参数用于复制对象的复制构造函数 函数原型的形式为Complex Complex 形参是本类对象的引用 现在又要介绍一种新的构造函数 转换构造函数 转换构造函数只有一个形参 如Complex doubler real r imag 0 其作用是将double型的参数r转换成Complex类的对象 将r作为复数的实部 虚部为0 用户可以根据需要定义转换构造函数 在函数体中告诉编译系统怎样去进行转换 在类体中 可以有转换构造函数 也可以没有转换构造函数 视需要而定 以上几种构造函数可以同时出现在同一个类中 它们是构造函数的重载 编译系统会根据建立对象时给出的实参的个数与类型选择形参与之匹配的构造函数 使用转换构造函数将一个指定的数据转换为类对象的方法如下 1 先声明一个类 2 在这个类中定义一个只有一个参数的构造函数 参数的类型是需要转换的类型 在函数体中指定转换的方法 3 在该类的作用域内可以用以下形式进行类型转换 类名 指定类型的数据 就可以将指定类型的数据转换为此类的对象 classComplex public Complex real 0 imag 0 Complex doubler doublei real r imag i Complex doubler real r imag 0 Complexoperator Complexc2 friendostream ComplexComplex operator Complexc2 returnComplex real c2 real imag c2 imag ostream intmain Complexc1 3 6 c2 c2 c1 Complex 8 2 c2 c1 Comples 8 2 c2 c1 8 c2 8 c1 cout c2 endl return0 classComplex public Complex real 0 imag 0 Complex doubler doublei real r imag i Complex doubler real r imag 0 friendComplexoperator Complexc1 Complexc2 friendostream Complexoperator Complexc1 Complexc2 returnComplex c1 real c2 real c1 imag c2 imag ostream intmain Complexc1 3 6 c2 c2 8 c1 okcout c2 endl return0 对称运算符一般重载为友元函数 10 8 3类型转换函数 用转换构造函数可以将一个指定类型的数据转换为类的对象 但是不能反过来将一个类的对象转换为一个其他类型的数据 例如将一个Complex类对象转换成double类型数据 C 提供类型转换函数 typeconversionfunction 来解决这个问题 类型转换函数的作用是将一个类的对象转换成另一类型的数据 类型转换函数的一般形式为operator类型名 实现转换的语句 在函数名前面不能指定函数类型 函数没有参数 其返回值的类型是由函数名中指定的类型名来确定的 类型转换函数只能作为成员函数 因为转换的主体是本类的对象 如果已声明了一个Complex类 可以在Complex类中这样定义类型转换函数 operatordouble returnreal double类型经过重载后 除了原有的含义外 还获得新的含义 将一个Complex类对象转换为double类型数据 并指定了转换方法 这样 编译系统不仅能识别原有的double型数据 而且还会把

温馨提示

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

评论

0/150

提交评论