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

下载本文档

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

文档简介

1、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)令实数xrA+B ; 2)令实数A, B 分别为实数 R,S 的立方根: 3)令 R = -q/2 + a, S = -q/2a ; (5.2) 4)令 a = sqrt (q/2) *(q/2) + (q/3) * (q/3) * (q/3)

2、; 实际的计算过程为: 用(4)计算得到a ; 用(3)计算得到 R 和S ;求出 R 和 S 的立方根 A 和 B ;最后得到实根xr。,3,5.1 三次方程求根程序的设计,计算立方根的迭代公式 Float cuberoot(float x)/精确到小数点后6位 float root , croot; const float eps1e6; crootx;do rootcroot; croot(2*rootx/(root*root)/3; while(fabs(crootroot)eps); return(croot); ,4,5.1 三次方程求根程序的设计,# includeiostrea

3、m.h /program5-1 # includemath.h float cuberoot(float); void main(void) float p, q, xr; coutInput parameters p,q: ; cinpq; float asqrt (q/2) *(q/2) + (q/3) * (q/3) * (q/3) ; xrcuberoot(q2a)cuberoot(q2a); coutendlThe real root of the equation isxr; float cuberoot(float x) ,5,5.1 三次方程求根程序的设计,课本p129显示了不

4、使用函数的程序。其中croot 的立方根的运算进行了两次,所以该计算程序要重复两次, 当程序较长,或计算次数更多时,采用“子程序”的方案可以大大缩短程序的长度。 特别是当程序比较复杂时,可以使得程序显得清晰,在program5_1 中,main()中不涉及计算立方根的细节,显得简洁,而在cuberoot()中只解决一个浮点数的立方根的计算,也很清楚。 另外,还可以把立方根的计算与C+语言中的运算符和标准函数对应起来,当在程序中对于cuberoot(y)给出了定义之后,就可以在主函数或其它用户定义的函数中,像运算符或标准函数那样使用了,如cuberoot(x)的使用与a+b, sin(x)的使用

5、没有什么区别。,6,5.2 函数的说明与使用- 参看书p130的5.2节,C+程序允许两种函数说明语句的形式,我们把它们分别称为函数原型(或函数声明)和函数定义。 1函数原型 函数原型(亦称函数声明)用来指出函数的名称,类型和参数,其格式为: 属性说明类型函数名(参数表); int add (int a, int b); inline void swap (float void print (char *) ;,7,5.2.1 函数的说明,属性说明:可缺省,一般可以是下面的关键字之一:inline,static,virtual, friend 等。 inline 表示该函数为内联函数; sta

6、tic 表示该函数为静态函数; virtual 表示该函数为虚函数; friend 表示该函数为某类(class)的友元函数。 类型:指函数的返回类型。 函数名:一个标识符。 参数表:它可能为空,void 或类型参数名,类型参数名 的形式。 main() ,print(void) , cuberoot(float x) , add(int a,int b),8,5.2.1 函数的说明,2函数定义 函数定义与函数原型的主要区别是它还包括函数体,其格式为: 属性说明类型函数名(参数表)函数体 属性说明,返回类型,函数名与函数原型一致,参数表中不可省略参数名。 函数体:由和括起来的复合语句即程序块。

7、program 5_1 的最后12 行就是一个函数定义。,9,函数的分类方法,1 从使用角度分类 2 从函数形式分类,10,(1)从使用角度分类,从使用角度划分,可将函数分为:系统预定义的标准库函数(如,sin,abs等),以及由用户自定义的函数。 程序中可直接使用(调用)系统预定义的标准库函数,但要求在调用前使用编译预处理指令include将对应的头文件包含进来。 由用户自定义的函数与系统预定义的标准库函数的不同点在于,自定义函数的函数名、参数个数、函数返回值类型以及函数所实现的功能等都完全由用户程序来规定(指定)。,11,(2)从函数形式分类,从函数形式划分,可分为无参函数与有参函数两类。

8、对无参函数来说,调用它们时不需要提供实际参数;而对有参函数进行调用时,必须提供所需个数的且具有相匹配数据类型的实际参数。,12,无参函数的定义,。 无参函数定义的一般形式 () . 通常用于实现某种固定功能。例如: void printStar() . 就自定义了一个叫做printStar的无参函数,比如可用它来实现打印出一行共10个“*”的固定功能。,13,有参函数定义的一般形式, ( ) . 通过调用处提供的不同实参值来计算出其对应的函数值、或实现某种与传递过来的那些不同值有关的某种功能。例如: void printStar(int k) . 就自定义了一个叫做printStar的具有1个

9、int型形参k的函数,比如可用它来实现打印出一行共k个“*”的自定义功能。,14,5.2.2 函数的调用,函数调用是已定义函数的一次实际运行,与某类型的一个变量和后文中某类的一个对象类似,函数调用是函数定义的一个“实例”。在C+程序中,除main函数外,其它任一函数的执行都是通过在main函数中直接或间接地调用该函数而引发的。调用一个函数就是去执行该函数之函数体的过程。 对无参函数进行调用的一般形式为: () 例如:printStar();,15,对有参函数进行调用的一般形式为:, ( ) 例如:printStar(26); 其中函数说明中的参数称为形式参数(形参),函数调用中的参数称为实际参

10、数(实参)。实参表在参数个数、参数顺序、以及参数类型等方面要与被调函数的形参表之间有一个一一对应的相互匹配关系。编译器将根据参数的顺序,来逐一实现实参与对应形参的“结合”,而后执行一遍函数体(而完成本次的函数调用)。,16,计算机对函数进行调用的执行顺序,以Program5-1为例 (1) 根据调用语句中的函数名(cuberoot)在整个程序中搜索同名函数定义; (2) 对实参数的参数个数,类型,顺序进行核对,判定是否与函数定义中的形参表对应一致,在上例中只有一个浮点型参数; (3) 根据参数的类型(值参数或引用参数)进行值参数的值传递或引用参数的换名,在上例中即是要把实参表达式的值计算出来赋

11、给形参x; (4) 运行函数体代码; (5) 返回调用点,并返回所要求的函数值,即返回计算结果croot 的值。,17,关于函数原型的一点说明,当函数调用从书写顺序上先于函数定义时,C+要求必须事先列出这一函数的函数原型。 (1)无参函数定义的函数原型 (); (2)有参函数定义的函数原型 ( ); 注意,与函数定义的一般形式相比,相当于用分号代换了函数体,而成为其相应的函数原型。,18,5.2.3 函数的返回,函数的返回完成两项任务: (1) 把运行控制从函数体返回到函数调用点。 在program5-1中就是在计算cuberoot (-q/2+a) 之后再返回到语句 xr = cuberoo

12、t () + cuberoot () 的计算过程中。 (2) 根据返回值要求,返回所需要的数据值。,19,5.2.3 函数的返回,函数的返回值有下面几种情形: 1.返回void 类型 如果函数无值返回,应说明为void 类型。未作类型说明的函数,系统认为是int 类型函数,应返回一整型值。 2返回数值类型 最常见的函数是返回一个数值的函数。 例如: int add(int a,int b); 当函数要返回的数值不止一个时,情况比较复杂,一般它可以以结构或类的形式,也可以以结构,数组或对象指针类型方式实现,这样的实例在后面的章节可以见到。 3返回引用类型 值返回方式是C 和Pascal 语言中唯

13、一的返回方式,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.90618 Input a=10 f(a)=50,21,程序编制:,#include double f

14、 (double x) double y; y=(x*x+x+1)/2-5.5; return (y); /对非void类型的函数,必须有一个 /return语句,由它返回函数值 ,22,void main() double z,a; z=(f(2.5)+2*f(6)/f(4.3); /调用自定义函数f couta; coutf(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句括号内表达式的

15、值,即为整个函数的返回值。 (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用于立即从被

16、调函数中返回, 当函数类型为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.90618 Input

17、 a=10 f(a)=50,27,程序编制:,#include double f (double x); /函数f的原型 void main() /同上,从略 double f (double x) /被调函数f的具体定义 /同上,从略 ,28,3. 实例3 - 无参函数,实现固定功能,编无参函数,void printStar(),它负责完成固定功能:在同一行连续显示60个“*”。并编制主函数main,对该函数实现调用,使程序执行后的显示结果如下: the result of first call to printStar(): * the result of second call to p

18、rintStar(): *,29,程序编制:,#include void printStar() /自定义无参函数printStar for(int i=1; i=60; i+) /显示60个“*” cout*; coutendl; return; ,30,void main() coutthe result of first call to printStar():endl; printStar();/对printStar的第一次调用 coutthe result of second call to printStar():endl; printStar();/对printStar的第二次调

19、用 ,31,点评:,(1)将printStar定为void类型,是因为不需要它返回任何值。 (2)按语句方式调用printStar(而不可作为表达式因子,如3+printStar()/2等)。 (3)printStar函数中的return用于立即从被调函数中返回到主调函数处(跳转到调用语句的下一语句处)去执行,当函数类型为void时,应使用这种无返回值的return语句。实际上,由于本函数是在执行完函数体内的所有语句后才返回,此种情况下的return语句可以缺省。,32,4. 实例4 - 一参函数,编一参函数,void printStar(int k),它负责显示出k行“*”来,其中每行均显示

20、连续的8个“*”。并编制主函数main,对该函数实现调用,使程序执行后的显示结果样式如下: k=? 3 * * *,33,程序编制:,#include void printStar(int k) /k为形参,由调用处的实参提供实际值 for(int i=1; ik; printStar(k); /函数调用,带去输入的实参k ,34,5. 实例5 - 二参函数,编二参函数,void printStar(int k, int n),它负责显示出k行“*”来,且每行均显示连续的n个“*”。并编制主函数,对该函数实现调用,使程序执行后的显示结果样式如下: k,n=? 4 15 * * * *,35,程

21、序编制:,#include void printStar(int k, int n) /负责显示出k行*来,且每行均显示连续的n个* for(int i=1; i=k; i+) /循环k次,显示出k行“*” for(int j=1; j=n; j+) /循环n次,显示出1行的n个“*” cout*; coutendl; /注意,函数末右花括号前缺省了一个return语句,36,void main() int k,n; /显示出k行,每行显示n个“*” coutkn; printStar(k, n); /以输入的k与n为实参去调用printStar ,37,6. 实例6 - 无参函数,全局变量,

22、编无参函数,void printStar(),并结合使用全局变量k与n,使每调用一次该函数,总显示出k行“*”来,且每行均显示连续的n个“*”,并编制主函数,对该函数实现调用,使程序执行后的显示结果样式如下: k,n=? 3 20 * * *,38,程序编制:,#include int k,n; /int型全局变量k,n /* 在所有函数之外(即在不属于任一函数定义的外面)说明的变量为全局变量,其作用域即有效区域为整个文件(或具有多个文件的整个程序,详细请参看本章的5.7及5.8节)。 */,39,void printStar() /无参函数printStar /其中所用的k与n都是全局变量

23、for(int i=1; i=k; i+)/显示出k行“*” for(int j=1; j=n; j+) /显示n个“*” cout*; coutendl; ,40,void main() coutkn;/输入全局变量k,全局变量n的值 coutthe result of call to printStar():endl; printStar(); /调用无参函数printStar ,41,5.2.4 函数的参数,C+语言允许函数无参,有一个或多个参数,而且还支持不定个数参数的函数。 无参函数:用void 或空表示无参。 一个或多个参数:多数函数有一个或多个确定的个数、确定的类型和顺序的参数。

24、 在C+语言中,不同的函数是根据函数名和参数表二者来区分的,只有二者完全一致才是同一函数。 (3)不定个数参数: 有些应用问题中参数个数是变化的。 例如设计一个电话计费函数,为了计算通话费,不同的通话类型(如市话,长途,数据与通讯,BP 机等)有不同数目的参数。 处理参数个数不定的情形,可有不同的途径:例如指针,C+提供的某些库函数,无名参数,可缺省参数等。,42,无名参数 -,C+ 语言,允许参数表中包含无名参数,主要是为了区分函数, 例如: int f(int a,int b)return ab*b; int f(int a,int b,int)return a*ab; 两个不同的函数同名

25、,但由于第二个函数包含一无名参数,使得在调用时能够被区分,f(x,y)是第一个函数的调用,f(x,y,0)是第二个函数的调用。,43,可缺省参数(参数默认值) -,允许在函数定义处为其中最后面的连续若干个参数设置默认值(也称缺省值),从而为调用处提供了方便(若调用处缺省了某个或某些实参的情况下,系统将自动使用那些在函数定义处给定的参数默认值)。 下面是一个示例性程序,在定义函数func时为它的最后面的连续3个参数(也即它的所有参数)都设置了默认值。若调用处缺省了某个或某些实参的情况下,系统将自动使用这些给定的参数默认值。,44,#include void func(int a=11, int

26、b=22, int c=33) /为参数a、b、c设置了默认值11、22与33 couta=a, b=b, c=cendl; ,45,void main() func(); /调用时缺省了3个实参,将使用 /定义处给定的那3个相对应的参数默认值 func(55); /调用时缺省了后2个实参,将使用 /定义处给定的那后2个对应参数默认值 func(77,99); /调用时缺省了最后1个实参,将使用 /定义处给定的那最后1个参数默认值 func(8,88,888); /调用时没缺省任一个实参,系统将 /不使用定义处给定的任一个参数默认值 ,46,程序执行后的显示结果如下:,a=11, b=22,

27、c=33 a=55, b=22, c=33 a=77, b=99, c=33 a=8, b=88, c=888,47,注意,只能为函数最后面的连续若干个参数设置默认值,且在调用处也只能缺省后面的连续若干个实参。,void func(int a, int b=2, int c=3); /OK! void func(int a=1, int b, int c=3); /ERROR! 对第一个函数说明,采用如下的调用语句: func(1, 22, 333); /OK! 调用时给出所有实参 func(); / ERROR! 参数a没有默认值 func(10, 20); /OK! 参数c默认为3 fun

28、c(5, , 9); / ERROR! 调用处也只能缺省后面的连续若干个实参,48,5.2.5 值调用和引用调用,C+语言在进行函数调用时,对参数的处理有两种方式,赋值型和引用型,即值调用方式和引用调用方式。前者是普通的形式,在C 语言中只有这种方式;C+语言中增加了引用调用形式,这种形式与pascal 语言中的变量参数调用方式相似。 1 赋值调用 2 引用调用,49,赋值调用 -,赋值形参:在函数定义的参数中,除了被说明为引用( /它所用的两个参数均为赋值参数。 void swap(int /它所用的第一个参数为赋值参数 /另一个为引用参数。 语法要求:调用函数时,引用参数对应的实参必须是指

29、定类型的变量。,53,对函数进行调用的执行过程(步骤):,(1) 将对应实参表达式的值赋给赋值形参(若参数为赋值参数的话); (2) 用实参变量替换相应的形参(若参数为引用参数的话); (3) 按各形参的“当前值”(或已被“赋值”,或已被“换名”)去执行一遍函数体并返回调用处。,54,注意:,(1) 通过赋值参数来传值的方式是一种“单向传值”方式,它只可向被调函数的形参“传入”值,而不可通过该形参“传出”值。 (2) 通过引用参数来传值的方式是一种“双向传值”方式,它不仅可向被调函数的形参“传入”值,而且还可通过该形参“传出”值。,55,实例,通过下面的小例子来理解赋值参数与引用参数的使用区别。 #include void f1(int /函数原型 /

温馨提示

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

最新文档

评论

0/150

提交评论