a函数与运算符的重载.ppt

上传人:tia****nde 文档编号:8952463 上传时间:2020-04-02 格式:PPT 页数:64 大小:937KB
返回 下载 相关 举报
a函数与运算符的重载.ppt_第1页
第1页 / 共64页
a函数与运算符的重载.ppt_第2页
第2页 / 共64页
a函数与运算符的重载.ppt_第3页
第3页 / 共64页
点击查看更多>>
资源描述
1 第5章函数与运算符的重载 5 1三次方程求根程序的设计5 2函数的说明与使用5 3函数的嵌套与递归5 4函数与运算符的重载5 5函数与C 程序结构5 6程序实例 2 5 1三次方程求根程序的设计 计算三次方程x3 px q 0的一个实根的公式为xr 为了从系数p q计算实根xr 把公式的计算分解为下面几步 1 令实数xr A B 2 令实数A B分别为实数R S的立方根 3 令R q 2 a S q 2 a 5 2 4 令a sqrt q 2 q 2 q 3 q 3 q 3 实际的计算过程为 用 4 计算得到a 用 3 计算得到R和S 求出R和S的立方根A和B 最后得到实根xr 3 5 1三次方程求根程序的设计 计算立方根的迭代公式Floatcuberoot floatx 精确到小数点后6位floatroot croot constfloateps 1e 6 croot x do root croot croot 2 root x root root 3 while fabs croot root eps return croot 4 5 1三次方程求根程序的设计 include iostream h program5 1 include math h floatcuberoot float voidmain void floatp q xr cout Inputparametersp q cin p q floata sqrt q 2 q 2 q 3 q 3 q 3 xr cuberoot q 2 a cuberoot q 2 a cout endl Therealrootoftheequationis xr floatcuberoot floatx 5 5 1三次方程求根程序的设计 课本p129显示了不使用函数的程序 其中croot的立方根的运算进行了两次 所以该计算程序要重复两次 当程序较长 或计算次数更多时 采用 子程序 的方案可以大大缩短程序的长度 特别是当程序比较复杂时 可以使得程序显得清晰 在program5 1中 main 中不涉及计算立方根的细节 显得简洁 而在cuberoot 中只解决一个浮点数的立方根的计算 也很清楚 另外 还可以把立方根的计算与C 语言中的运算符和标准函数对应起来 当在程序中对于cuberoot y 给出了定义之后 就可以在主函数或其它用户定义的函数中 像运算符或标准函数那样使用了 如cuberoot x 的使用与a b sin x 的使用没有什么区别 6 5 2函数的说明与使用 参看书p130的5 2节 C 程序允许两种函数说明语句的形式 我们把它们分别称为函数原型 或函数声明 和函数定义 1 函数原型函数原型 亦称函数声明 用来指出函数的名称 类型和参数 其格式为 属性说明 类型 函数名 参数表 intadd inta intb inlinevoidswap floatvoidprint char 7 5 2 1函数的说明 属性说明 可缺省 一般可以是下面的关键字之一 inline static virtual friend等 inline表示该函数为内联函数 static表示该函数为静态函数 virtual表示该函数为虚函数 friend表示该函数为某类 class 的友元函数 类型 指函数的返回类型 函数名 一个标识符 参数表 它可能为空 void或 类型 参数名 类型 参数名 的形式 main print void cuberoot floatx add inta intb 8 5 2 1函数的说明 2 函数定义函数定义与函数原型的主要区别是它还包括函数体 其格式为 属性说明 类型 函数名 参数表 函数体 属性说明 返回类型 函数名与函数原型一致 参数表中不可省略参数名 函数体 由 和 括起来的复合语句即程序块 program5 1的最后12行就是一个函数定义 9 函数的分类方法 1从使用角度分类2从函数形式分类 10 1 从使用角度分类 从使用角度划分 可将函数分为 系统预定义的标准库函数 如 sin abs等 以及由用户自定义的函数 程序中可直接使用 调用 系统预定义的标准库函数 但要求在调用前使用编译预处理指令include将对应的头文件包含进来 由用户自定义的函数与系统预定义的标准库函数的不同点在于 自定义函数的函数名 参数个数 函数返回值类型以及函数所实现的功能等都完全由用户程序来规定 指定 11 2 从函数形式分类 从函数形式划分 可分为无参函数与有参函数两类 对无参函数来说 调用它们时不需要提供实际参数 而对有参函数进行调用时 必须提供所需个数的且具有相匹配数据类型的实际参数 12 无参函数的定义 无参函数定义的一般形式 通常用于实现某种固定功能 例如 voidprintStar 就自定义了一个叫做printStar的无参函数 比如可用它来实现打印出一行共10个 的固定功能 13 有参函数定义的一般形式 通过调用处提供的不同实参值来计算出其对应的函数值 或实现某种与传递过来的那些不同值有关的某种功能 例如 voidprintStar intk 就自定义了一个叫做printStar的具有1个int型形参k的函数 比如可用它来实现打印出一行共k个 的自定义功能 14 5 2 2函数的调用 函数调用是已定义函数的一次实际运行 与某类型的一个变量和后文中某类的一个对象类似 函数调用是函数定义的一个 实例 在C 程序中 除main函数外 其它任一函数的执行都是通过在main函数中直接或间接地调用该函数而引发的 调用一个函数就是去执行该函数之函数体的过程 对无参函数进行调用的一般形式为 例如 printStar 15 对有参函数进行调用的一般形式为 例如 printStar 26 其中函数说明中的参数称为形式参数 形参 函数调用中的参数称为实际参数 实参 实参表在参数个数 参数顺序 以及参数类型等方面要与被调函数的形参表之间有一个一一对应的相互匹配关系 编译器将根据参数的顺序 来逐一实现实参与对应形参的 结合 而后执行一遍函数体 而完成本次的函数调用 16 计算机对函数进行调用的执行顺序 以Program5 1为例 1 根据调用语句中的函数名 cuberoot 在整个程序中搜索同名函数定义 2 对实参数的参数个数 类型 顺序进行核对 判定是否与函数定义中的形参表对应一致 在上例中只有一个浮点型参数 3 根据参数的类型 值参数或引用参数 进行值参数的值传递或引用参数的换名 在上例中即是要把实参表达式的值计算出来赋给形参x 4 运行函数体代码 5 返回调用点 并返回所要求的函数值 即返回计算结果croot的值 17 关于函数原型的一点说明 当函数调用从书写顺序上先于函数定义时 C 要求必须事先列出这一函数的函数原型 1 无参函数定义的函数原型 2 有参函数定义的函数原型 注意 与函数定义的一般形式相比 相当于用分号代换了函数体 而成为其相应的函数原型 18 5 2 3函数的返回 函数的返回完成两项任务 1 把运行控制从函数体返回到函数调用点 在program5 1中就是在计算cuberoot q 2 a 之后再返回到语句xr cuberoot cuberoot 的计算过程中 2 根据返回值要求 返回所需要的数据值 19 5 2 3函数的返回 函数的返回值有下面几种情形 1 返回void类型如果函数无值返回 应说明为void类型 未作类型说明的函数 系统认为是int类型函数 应返回一整型值 2 返回数值类型最常见的函数是返回一个数值的函数 例如 intadd inta intb 当函数要返回的数值不止一个时 情况比较复杂 一般它可以以结构或类的形式 也可以以结构 数组或对象指针类型方式实现 这样的实例在后面的章节可以见到 3 返回引用类型值返回方式是C和Pascal语言中唯一的返回方式 C 语言提供的引用返回概念是一种很强的功能 当函数定义中把该函数说明为某类型的引用类型时 该函数调用后返回的不单是值 而是包含返回值的变量 或对象 由于返回引用与引用类型有关 所以这样的实例将在下节介绍 20 函数应用实例 1 实例1 无须给出函数f的原型设f x x x x 1 2 5 5 1 求z f 2 5 2 f 6 f 4 3 并显示结果z 2 对任意输入的一个实数a 求出f a 并显示 程序执行后的交互结果如下 z 4 90618Inputa 10f a 50 21 程序编制 includedoublef doublex doubley y x x x 1 2 5 5 return y 对非void类型的函数 必须有一个 return语句 由它返回函数值 22 voidmain doublez a z f 2 5 2 f 6 f 4 3 调用自定义函数fcout a cout f a f a endl 算出f a 并输出 23 点评 1 main中共出现了4次对自定义函数f的调用 2 编写f函数时的3点注意 1 f函数体内的3行也可用如下的一行来代替return x x x 1 2 5 5 return句括号内表达式的值 即为整个函数的返回值 2 return句也可使用另一格式 即可以不括起表达式 return x x x 1 2 5 5 OK 24 3 三种不正确的用法 f x x x 1 2 5 5 不可给函数名f赋值 return f 返回值类型应该是double 而非指针类型 函数名相当于一个指针 f x x x x 1 2 5 5 赋值号左端非变量 也即f x 非左值 25 3 关于return语句 return语句 称为返回语句 具有如下三种使用格式 return return return 第一种格式的return用于立即从被调函数中返回 当函数类型为void时 应使用这种格式的返回语句 当函数类型为非void型时 应使用第二或第三种格式的return语句 此两种格式的语句效果完全相同 可将第二种格式看成是第三种格式的省略形式 系统此时都将计算出表达式的值 并 携带 该值立即从被调函数中返回 26 2 实例2 main在前而被调函数f在后时 必须先列出函数f的原型 设f x x x x 1 2 5 5 1 求z f 2 5 2 f 6 f 4 3 并显示结果z 2 对任意输入的一个实数a 求出f a 并显示 程序执行后的交互结果如下 z 4 90618Inputa 10f a 50 27 程序编制 includedoublef doublex 函数f的原型voidmain 同上 从略 doublef doublex 被调函数f的具体定义 同上 从略 28 3 实例3 无参函数 实现固定功能 编无参函数 voidprintStar 它负责完成固定功能 在同一行连续显示60个 并编制主函数main 对该函数实现调用 使程序执行后的显示结果如下 theresultoffirstcallto printStar theresultofsecondcallto printStar 29 程序编制 includevoidprintStar 自定义无参函数printStarfor inti 1 i 60 i 显示60个 cout cout endl return 30 voidmain cout theresultoffirstcallto printStar endl printStar 对printStar的第一次调用cout theresultofsecondcallto printStar endl printStar 对printStar的第二次调用 31 点评 1 将printStar定为void类型 是因为不需要它返回任何值 2 按语句方式调用printStar 而不可作为表达式因子 如3 printStar 2等 3 printStar函数中的return用于立即从被调函数中返回到主调函数处 跳转到调用语句的下一语句处 去执行 当函数类型为void时 应使用这种无返回值的return语句 实际上 由于本函数是在执行完函数体内的所有语句后才返回 此种情况下的return语句可以缺省 32 4 实例4 一参函数 编一参函数 voidprintStar intk 它负责显示出k行 来 其中每行均显示连续的8个 并编制主函数main 对该函数实现调用 使程序执行后的显示结果样式如下 k 3 33 程序编制 includevoidprintStar intk k为形参 由调用处的实参提供实际值for inti 1 i k printStar k 函数调用 带去输入的实参k 34 5 实例5 二参函数 编二参函数 voidprintStar intk intn 它负责显示出k行 来 且每行均显示连续的n个 并编制主函数 对该函数实现调用 使程序执行后的显示结果样式如下 k n 415 35 程序编制 includevoidprintStar intk intn 负责显示出k行 来 且每行均显示连续的n个 for inti 1 i k i 循环k次 显示出k行 for intj 1 j n j 循环n次 显示出1行的n个 cout cout endl 注意 函数末右花括号前缺省了一个return语句 36 voidmain intk n 显示出k行 每行显示n个 cout k n printStar k n 以输入的k与n为实参去调用printStar 37 6 实例6 无参函数 全局变量 编无参函数 voidprintStar 并结合使用全局变量k与n 使每调用一次该函数 总显示出k行 来 且每行均显示连续的n个 并编制主函数 对该函数实现调用 使程序执行后的显示结果样式如下 k n 320 38 程序编制 includeintk n int型全局变量k n 在所有函数之外 即在不属于任一函数定义的外面 说明的变量为全局变量 其作用域即有效区域为整个文件 或具有多个文件的整个程序 详细请参看本章的5 7及5 8节 39 voidprintStar 无参函数printStar 其中所用的k与n都是全局变量for inti 1 i k i 显示出k行 for intj 1 j n j 显示n个 cout cout endl 40 voidmain cout k n 输入全局变量k 全局变量n的值cout theresultofcallto printStar endl printStar 调用无参函数printStar 41 5 2 4函数的参数 C 语言允许函数无参 有一个或多个参数 而且还支持不定个数参数的函数 无参函数 用void或空表示无参 一个或多个参数 多数函数有一个或多个确定的个数 确定的类型和顺序的参数 在C 语言中 不同的函数是根据函数名和参数表二者来区分的 只有二者完全一致才是同一函数 3 不定个数参数 有些应用问题中参数个数是变化的 例如设计一个电话计费函数 为了计算通话费 不同的通话类型 如市话 长途 数据与通讯 BP机等 有不同数目的参数 处理参数个数不定的情形 可有不同的途径 例如指针 C 提供的某些库函数 无名参数 可缺省参数等 42 无名参数 C 语言 允许参数表中包含无名参数 主要是为了区分函数 例如 intf inta intb returna b b intf inta intb int returna a b 两个不同的函数同名 但由于第二个函数包含一无名参数 使得在调用时能够被区分 f x y 是第一个函数的调用 f x y 0 是第二个函数的调用 43 可缺省参数 参数默认值 允许在函数定义处为其中最后面的连续若干个参数设置默认值 也称缺省值 从而为调用处提供了方便 若调用处缺省了某个或某些实参的情况下 系统将自动使用那些在函数定义处给定的参数默认值 下面是一个示例性程序 在定义函数func时为它的最后面的连续3个参数 也即它的所有参数 都设置了默认值 若调用处缺省了某个或某些实参的情况下 系统将自动使用这些给定的参数默认值 44 includevoidfunc inta 11 intb 22 intc 33 为参数a b c设置了默认值11 22与33cout a a b b c c endl 45 voidmain func 调用时缺省了3个实参 将使用 定义处给定的那3个相对应的参数默认值func 55 调用时缺省了后2个实参 将使用 定义处给定的那后2个对应参数默认值func 77 99 调用时缺省了最后1个实参 将使用 定义处给定的那最后1个参数默认值func 8 88 888 调用时没缺省任一个实参 系统将 不使用定义处给定的任一个参数默认值 46 程序执行后的显示结果如下 a 11 b 22 c 33a 55 b 22 c 33a 77 b 99 c 33a 8 b 88 c 888 47 注意 只能为函数最后面的连续若干个参数设置默认值 且在调用处也只能缺省后面的连续若干个实参 voidfunc inta intb 2 intc 3 OK voidfunc inta 1 intb intc 3 ERROR 对第一个函数说明 采用如下的调用语句 func 1 22 333 OK 调用时给出所有实参func ERROR 参数a没有默认值func 10 20 OK 参数c默认为3func 5 9 ERROR 调用处也只能缺省后面的连续若干个实参 48 5 2 5值调用和引用调用 C 语言在进行函数调用时 对参数的处理有两种方式 赋值型和引用型 即值调用方式和引用调用方式 前者是普通的形式 在C语言中只有这种方式 C 语言中增加了引用调用形式 这种形式与pascal语言中的变量参数调用方式相似 1赋值调用2引用调用 49 赋值调用 赋值形参 在函数定义的参数中 除了被说明为引用 的参数之外 其余所有类型的形参都属于赋值形参 过程 在执行函数调用时 在检查函数名及参数表之后 首先为值参数分配内存 然后计算各对应的实参表达式 并把计算的值赋给刚刚创建的参数变量 进而开始函数体的运行 凡是赋值形参 在函数的每次调用时 都必须为每一个赋值形参创建一个新的参数变量 实参表达式 另一方面 函数调用语句中 与赋值形参相对应的实参可以是指定类型的常量 变量或表达式 在执行函数调用时应把该表达式的值计算出来 作为初值赋给刚刚为赋值形参创建的参数变量 这是赋值调用方式名称的由来 为赋值形参创建的参数变量是局限于函数体运行的局部变量 它作为该形参的一个实例 参加函数体程序块的这次运行 一旦运行完毕 这个参数变量就被撤消 50 引用调用 函数定义的参数表中 名字前加上符号 的参数为引用形参 例如voidswap int a int b 引用形参在调用过程中的参数传递机制不同于赋值形参 其要点是 1 函数的调用语句中对应于引用形参的实参必须是同一类型的变量 非变量的表达式则不允许 2 参数传递的内容不是实参的值 而是地址 其实际的效果是令对应的引用形参在调用过程中 作为一个变量名指向作为实参的这个变量 与赋值形参的不同在这里体现出来 在引用调用过程中并不创建新的参数变量 3 在函数体程序块的运行中 引用形参的每次出现 由于它现在已经是指向实参变量 因此相当于全用实参变量所代替 即起到了所谓的 换名 的作用 4 在函数体程序运行结束 控制转回调用点时 该引用形参与实参变量的对应关系也就终止了 但是在调用过程中对于这个实参变量的所有处理和操作的结果 却保留下来 这一点也是区别于赋值调用的 51 引用调用 设计函数在下面两种情形时 需要改变某些变量的值 上述函数swap就是一例 对于占内存较多的数据参数 为了不另建新的参数变量以节省内存 建议采用引用参数 在后一种情况 为了保证实参不在函数中被修改 可在形参说明中加上const说明 例如 complexadd constcomplex a constcomplex b 而对于赋值形参 则无此必要 52 实例 voidprintStar intk intn 它所用的两个参数均为赋值参数 voidswap int 它所用的第一个参数为赋值参数 另一个为引用参数 语法要求 调用函数时 引用参数对应的实参必须是指定类型的变量 53 对函数进行调用的执行过程 步骤 1 将对应实参表达式的值赋给赋值形参 若参数为赋值参数的话 2 用实参变量替换相应的形参 若参数为引用参数的话 3 按各形参的 当前值 或已被 赋值 或已被 换名 去执行一遍函数体并返回调用处 54 注意 1 通过赋值参数来传值的方式是一种 单向传值 方式 它只可向被调函数的形参 传入 值 而不可通过该形参 传出 值 2 通过引用参数来传值的方式是一种 双向传值 方式 它不仅可向被调函数的形参 传入 值 而且还可通过该形参 传出 值 55 实例 通过下面的小例子来理解赋值参数与引用参数的使用区别 includevoidf1 int 函数原型 前两个为引用参数 可 双向传值 后两个为赋值参数 56 voidmain inti 1 j 2 k 77 n 88 cout Inmain beforcallingf1 endl cout i j k n i j k n endl endl f1 i j k n 注意 调用后实参变量i j的值进行了改变 而k与n的值并不改变cout Inmain aftercallingf1 endl cout i j k n i j k n endl 57 voidf1 int 58 程序执行后的显示结果如下 Inmain beforcallingf1 i j k n 127788 Enterf1 a b c d 127788 Intheendoff1 a b c d 218877 Inmain aftercallingf1 i j k n 217788 59 5 2 6内联函数 可在一般的函数说明前冠以关键字inline 称这样的函数为内联函数 按如下的方式来说明 inline 60 在编译过程中 凡内联函数 系统均把它的执行代码插入到该函数的每个调用点处 以取代那一函数调用 从而使程序执行过程中 每次对该函数调用时不需控制转移 可节省执行时间 但由于每个调用点处均出现那一函数的执行代码拷贝 相对来说使用内联函数后会扩大其代码空间 61 使用内联函数的简单实例 includeinlineintmax intx inty 内联函数max return x y x y 62 voidmain void inta b cout a b cout max a b max a b endl 对内联函数max的调用 63 程序执行后的显示结果如下 Inputa b 123456max a b 456使用内联函数时应注意 1 内联函数的函数体一般讲不宜过大 以1 5行为宜 2 凡在类体中定义的成员函数 见第7章 均隐含为内联函数 第五章前部分结束
展开阅读全文
相关资源
相关搜索

当前位置:首页 > 图纸专区 > 课件教案


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

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


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