函数,函数与运算符的重载.ppt_第1页
函数,函数与运算符的重载.ppt_第2页
函数,函数与运算符的重载.ppt_第3页
函数,函数与运算符的重载.ppt_第4页
函数,函数与运算符的重载.ppt_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

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

文档简介

1 函数在C 程序设计中的意义体现在四个方面 1 从历史上说 函数的思想来源于子程序 把程序中反复出现的相同或相近的程序改写成子程序 可以大大缩短程序的长度 函数实际上是参数化的子程序 2 从结构化程序设计 SP 的观点来看 更重要的是通过函数设计 可以把整个程序要完成的整体的复杂的计算任务 分解为一个个较小的 相对简单的子任务 这种模块化的程序易设计 易阅读 易调试 易维护 较少出错 3 从运算的角度说 函数就是C 语言提供的由用户定义的运算 运算符是系统提供的运算 而函数是由用户自己定义的运算 2 4 作为面向对象程序设计 OOP 语言的C 以类为核心 类由数据和方法组成 方法就是对数据的运算和处理 亦即类的函数成员 故函数设计同样是OOP的重要组成部分 5 1三次方程求根程序的设计 5 2函数的说明与使用 5 2 1函数说明 C 程序允许两种函数说明语句的形式 我们把它们分别称为函数原型 或函数声明 和函数定义 3 1 函数原型函数原型用来指出函数的名称 类型和参数 其格式为 属性说明 可缺省 一般可以是下面的关键字之一 inline static virtual friend等 inline表示该函数为内联函数 static表示该函数为静态 内部 函数 virtual表示该函数为虚函数 friend表示该函数为某类 class 的友元函数 4 函数原型一般在两种情形下被使用 在程序中某函数的调用语句出现在该函数的定义之前 这时必须在调用语句之前列出函数原型 为了类定义的简明清晰 一般把较大的函数成员定义移到类说明之外 这时应把该函数的原型列于类说明之中 5 2 函数定义函数定义与函数原型的主要区别是它还包括函数体 其格式为 属性说明 类型 函数名 参数表 函数体 属性说明 返回类型 函数名与函数原型一致 参数表中不可省略参数名 函数体 由 和 括起来的复合语句即程序块 6 5 2 2函数调用 函数调用是已定义函数的一次实际运行 与某类型的一个变量 某类的一个对象类似 函数调用也是函数定义的一个 实例 函数调用的两要素是函数名和实参表 具体的调用实施过程如下 1 根据调用语句中的函数名在整个程序中搜索同名函数定义 2 对实参数的参数个数 类型 顺序进行核对 判定是否与函数定义中的形参表对应一致 7 3 根据参数的类型 值参数或引用参数 进行值参数的值传递或引用参数的换名 4 运行函数体代码 5 返回调用点 并返回所要求的函数值 5 2 3函数的返回 函数的返回完成两项任务 把运行控制从函数体返回到函数调用点 根据返回值要求 返回所需要的数据值 8 函数的返回值有下面几种情形 1 返回void类型如果函数无值返回 应说明为void类型 2 返回数值类型最常见的函数是返回一个数值的函数 3 返回引用类型值返回方式是C和Pascal语言中唯一的返回方式 C 语言提供的引用返回概念是其特有的一种很强的功能 当函数定义中把该函数说明为某类型的引用类型时 该函数调用后返回的不单是值 而是包含返回值的变量 或对象 9 5 2 4函数的参数 C 语言允许函数无参 有一个或多个参数 而且还支持不定个数参数的函数 无参函数 其函数说明为下列形式 voidprint void intgetx 用void或空表示无参 2 一个或多个参数 3 不定个数参数 有些应用问题中参数个数是变化的 处理参数个数不定的情形 可有不同的途径 10 如 voidsort intn float a 这个函数可对n长的浮点数组进行排序 n是变化的 由于a是数组的首地址 因此这个函数实际上是可以进行对任意多个浮点数排序的处理 C 语言有的版本还提供一些库函数 支持处理形如 voidabc inti 的不定参数函数 C 语言 允许参数表中包含无名参数 主要是为了区分函数 例如 intf inta intb returna b b intf inta intb int returna a b 两个不同的函数同名 但由于第二个函数包含一无名参数 使得在调用时能够被区分 f x y 是第一个函数的调用 f x y 0 是第二个函数的调用 11 C 程序还允许为函数定义可缺省参数 即参数有默认值 当对应的实参缺省时 该形参将使用默认值 这种函数调用时具有灵活性 例如 intsqrsum inta intb intc 0 returna a b b c c 其中参数c为可缺省参数 下面的调用方式都是合法的 x y z为int型变量 sqrsum x y z sqrsum x y x y sqrsum x y 参数表中可有任意多个参数指定为可缺省参数 但所有可缺省参数必须列后 在调用该函数时 只能缺省后面的可缺省参数 可缺省参数例 p5 3 cpp 12 5 2 5值调用与引用调用 C 语言在进行函数调用时 对参数的处理有两种方式 即值调用方式和引用调用方式 前者是普通的形式 在C语言中只有这种方式 C 语言中增加了引用调用形式 这种形式与pascal语言中的变量参数调用方式相似 1 赋值调用方式 值调用方式 在函数定义的参数中 除了被说明为引用 的参数之外 其余所有类型的形参都属于赋值形参 凡是赋值形参 在函数的每次调用时 都必须为每一个赋值形参创建一个新的参数变量 13 函数调用语句中 与赋值形参相对应的实参可以是指定类型的常量 变量或表达式 为赋值形参创建的参数变量是局限于函数体运行的局部变量 它作为该形参的一个实例 参加函数体程序块的这次运行 一旦运行完毕 这个参数变量就被撤消 实参与形参即使同名 也没有直接的关系 调用该函数 仅仅传递实参的值 实参本身与函数调用过程无关 在调用之后其值不会改变 当一个函数有多个赋值形参时 在进行值传递过程中 多个实参表达式计算的次序将依赖于具体的编译系统 例如 realpara n n 14 2 引用调用方式 引用形参 函数定义的参数表中 名字前加上符号 的参数为引用形参 例如 voidswap int a int b inttemp a a b b temp 形参a b为引用形参 这时其函数原型可写为 voidswap int int 15 引用形参在调用过程中的参数传递机制不同于赋值形参 其要点是 1 函数的调用语句中对应于引用形参的实参必须是同一类型的变量 非变量的表达式则不允许 2 参数传递的内容不是实参的值 而是地址 其实际的效果是令对应的引用形参在调用过程中 作为一个变量名指向作为实参的这个变量 与赋值形参的不同在这里体现出来 在引用调用过程中并不创建新的参数变量 3 在函数体程序块的运行中 引用形参的每次出现 由于它现在已经是指向实参变量 因此相当于全用实参变量所代替 即起到了所谓的 换名 的作用 16 4 在函数体程序运行结束 控制转回调用点时 该引用形参与实参变量的对应关系也就终止了 但是在调用过程中对于这个实参变量的所有处理和操作的结果 却保留下来 这一点也是区别于赋值调用的 它不需要借助于指针类型 直接可以把函数处理结果带出函数 C 语言提供的引用调用方式 表面上看它与利用指针类型的形参的赋值调用所起的效果相同 实际上它优于指针方法 使用指针方法示例 voidswap int a int b inttemp a a b b temp 17 设计函数在下面两种情形时 建议采用引用参数 需要改变某些变量的值 上述函数swap就是一例 对于占内存较多的参数 如数组 对象参数 为了不另建新的参数变量以节省内存 在后一种情况 为了保证实参不在函数中被修改 可在形参说明中加上const说明 在函数体中不能改变其值 而对于赋值形参 则无此必要 例如 complexadd constcomplex a constcomplex b 值调用与引用调用例 p5 2 cpp 18 5 2 6内联函数 内联 inline 函数的设置是C 不同于C的特征之一 1 在C 程序中符合下列条件之一的函数为内联函数 函数说明前冠以 inline 关键字的函数 类内定义的函数成员 第7章介绍 2 在编译过程中 凡内联函数 系统把它的执行代码插入到该函数的每个调用点 从而使程序执行过程中 每次调用该函数时不需控制转移 但该函数代码可能有多个拷贝出现在目标程序中 19 3 一般把函数体短小而又频繁调用的函数说明为内联函数较好 内联函数体内一般不能有循环语句和switch语句 内联函数的定义必须出现在第一次调用之前 对内联函数不能进行异常接口声明 4 利用编译预处理的宏定义方式 也可以实现类似于内联函数的功能 不过 宏定义方式没有类型的概念 是不安全的 内联函数的方式更为方便和可靠 20 5 3函数的嵌套与递归 5 3 1函数嵌套 一个函数的函数体中包含一个或多个函数调用语句 即称为函数嵌套 函数嵌套调用所占用的空间 如赋值参数的创建等等 用堆栈 stack 的方式管理 一般这种堆栈所分配的空间是有限的 因此函数互相嵌套的层数也是有限的 依编译系统不同 其允许的嵌套层数也可能不同 21 嵌套调用和返回示图 调用f1函数 结束 f1函数 调用f2函数 结束 f2函数 结束 22 5 3 2函数的递归 函数A在其函数体中直接包含它自己的调用语句 函数A称为 直接 递归函数 函数A在其函数体中间接地包含对它自己的调用 例如A调用函数B 但函数B又调用函数A 则函数A称为 间接 递归函数 无论是直接递归还是间接递归都必须保证在有限次调用之后能够结束 函数调用时系统要付出时间和空间代价 在功能相同的情形下 总是非递归程序效率较高 23 利用递归调用求n 的函数 floatfac intn floatf if n 1 f 1 elsef fac n 1 n returnf 计算4 fac 4 的递归过程图 returnf 使fac 1 1 returnf 使fac 2 2 returnf 使fac 3 6 returnf 使fac 4 24 24 5 4函数与运算符的重载 函数重载实际上是函数名重载 即支持多个不同的函数采用同一名字 这一点在C语言和其它语言中是不允许的 函数的重载并不是为了节省标识符 而是为了方便程序员的使用 5 4 1函数重载 实现函数的重载必须满足下列条件之一 1 参数表中对应的参数类型不同 2 参数表中参数个数不同 3 参数表中不同类型参数的次序不同 重载函数例程 p5 0 cpp 25 在定义同名函数时应注意 1 返回类型不能区分函数 例如 floatadd int float intadd int float 错误 2 采用引用参数不能区分函数 例如 voidprint double voidprint double 错误voidprint constdouble 错误 3 有些派生基本类型的参数虽然可以区分同名函数 但在使用中必须注意可能出现二义性 26 4 包含可缺省参数时 可能造成二义性 程序设计中应避免这种情形出现 例如 intsum inta intb intc 0 intsum inta intb 5 参数名不能区分函数 例如 intsum inta intb intsum intx inty 6 不要将不同功能的函数定义为重载函数 以免出现对调用结果的误解 但语法上是允许的 27 遇到无准确匹配的函数定义时 C 系统并不马上按出错处理 它按下面的方式处理 1 通过数组名与指针变量 函数名与函数指针 某类型变量与const常量之间的转换 再查是否可实现匹配 2 把实参类型从低到高 按字长由短到长 进行基本类型及其派生类型的转换 再检查是否可匹配 3 查有无已定义的可变个数参数的函数 如有把它归为该函数 在进行上述尝试性的处理之后可能出现仍无匹配或匹配不唯一的情况 这时可能输出出错信息或错误地运行 28 5 4 2运算符重载 C 语言规定 大多数运算符都可以重载 包括 单目运算符 new delete双目运算符 算术运算 位运算 逻辑运算 关系运算 赋值运算 赋值运算 逗号运算 I O运算 其它 29 不可重载运算符包括 限定符 条件运算符 取长度运算符sizeof 算术运算符 逻辑运算符 位运算符和关系运算符中的 这些运算都与基本数据类型有关 通过运算重载函数的定义 使它们也用于某些用户定义的数据类型 赋值运算符 关系运算符 指针运算符 和 下标运算符 等 它们的运算所涉及的数据类型按C 程序规定 并非只限于基本数值类型 因此 这些运算符可以自动地扩展到任何用户定义的数据类型 一般不需作重载定义就可 自动 地实现重载 30 重载之后 运算符的优先级和结合性不会改变 一般来讲 重载的功能应与原有功能相类似 不能改变原运算符的操作数个数 同时至少要有一个操作对象是用户自定义类型 运算符重载的一般语法形式为 函数类型operator运算符 形参表 运算符重载函数的调用方式有两种 1 与原运算符相同的调用方式 如b1 b2 b1 b2 2 一般函数调用方式 如b1 b2 也可以写为operator b1 b2 例 复数加减 p5 1 cpp 31 在C 中运算符的重载一般针对类 重载有两种形式 重载为类的成员函数和重载为类外函数 当重载为类的成员函数时 函数的参数个数比原来的操作数个数要少一个 后缀 除外 当重载为类外函数时 函数的参数个数与原来的操作数个数相等 单目运算符 和 实际上各有两种用法 前缀增 减 量和后缀增 减 量 其运算符重载函数的定义当然是不同的 对两种不同的运算无法从重载函数的原型上予以区分 函数名 operator 和参数表完全一样 为了区别前缀 和后缀 C 语言规定 在后缀 的重载函数的原型参数表中增加一个int型的无名参数 其原型形式为 32 前缀 类型 operator 作为类成员 类型 operator 类型 作为类外函数后缀 类型 operator int 作为类成员 类型 operator 类型 int 作为类外函数关于减量运算符 的重载方式相同 其调用方法为 前缀 a或a operator operator a 后缀 a 或a operator 0 operator a 0 33 5 5函数与C 程序结构 5 5 1库函数的使用 库函数又叫标准函数 程序员可直接调用 但要在程序开头说明库函数所在的头文件 如 include include 5 5 2SP框架结构5 5 3函数间的数据传递 通过赋值参数和返回语句通过全局变量通过指针类型参数和引用型参数通过数组类型参数 本质上与指针类型参数相同 34 5 5 4变量与函数的作用域 1 外部存储属性与静态存储属性 整个程序 外部函数 类 非静态全局变量 程序文件 静态函数 静态全局变量 函数 局部变量 静态局部变量 形参 程序块 复合语句 块内定义的局部变量 C 程序中标识符的作用域

温馨提示

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

评论

0/150

提交评论