C++语言-南开大学第5章函数与运算符的重载a_第1页
C++语言-南开大学第5章函数与运算符的重载a_第2页
C++语言-南开大学第5章函数与运算符的重载a_第3页
C++语言-南开大学第5章函数与运算符的重载a_第4页
C++语言-南开大学第5章函数与运算符的重载a_第5页
已阅读5页,还剩59页未读 继续免费阅读

下载本文档

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

文档简介

1、1第第5 5章章 函数与运算符的重载函数与运算符的重载5.1 5.1 三次方程求根程序的设计三次方程求根程序的设计5.2 5.2 函数的说明与使用函数的说明与使用5.3 5.3 函数的嵌套与递归函数的嵌套与递归5.4 5.4 函数与运算符的重载函数与运算符的重载5.5 5.5 函数与函数与C+C+程序结构程序结构5.6 5.6 程序实例程序实例25.1 5.1 三次方程求根程序的设计三次方程求根程序的设计 - -计算三次方程计算三次方程x x3 3+px+q=0+px+q=0的一个实根的公式为的一个实根的公式为x xr r= =n为了从系数为了从系数p p、q q 计算实根计算实根x xr r

2、, ,把公式的计算分解为下面几把公式的计算分解为下面几步:步: 1 1)令实数)令实数x xr rA+B ;A+B ; 2 2)令实数)令实数A, B A, B 分别为实数分别为实数 R,S R,S 的立方根:的立方根: 3 3)令)令 R = -q/2 + a, S = -q/2R = -q/2 + a, S = -q/2a ; (5.2)a ; (5.2) 4 4)令)令 a = a = sqrtsqrt (q/2) (q/2) * *(q/2) + (q/3) (q/2) + (q/3) * * (q/3) (q/3) * * (q/3) ; (q/3) ; 实际的计算过程为:实际的计算

3、过程为: 用用(4)(4)计算得到计算得到a ; a ; 用用(3)(3)计算得到计算得到 R R 和和S S ;求出;求出 R R 和和 S S 的立方根的立方根 A A 和和 B ;B ;最后得到实根最后得到实根x xr r。 332332)3()2(2)3()2(2pqqpqq3 5.1 5.1 三次方程求根程序的设计三次方程求根程序的设计计算立方根的迭代公式计算立方根的迭代公式 Float Float cuberootcuberoot(float xfloat x)/精确到小数点后精确到小数点后6 6位位 float root , float root , crootcroot; co

4、nst float const float epseps1e1e6 6; crootcrootx x;dodo rootrootcrootcroot; crootcroot(2 2* *rootrootx/x/(rootroot* *rootroot)/3/3; whilewhile(fabsfabs(crootcrootrootroot)epseps);); returnreturn(crootcroot););210332,nnnryrryr4 5.1 5.1 三次方程求根程序的设计三次方程求根程序的设计# include# includeiostream.hiostream.h /pro

5、gram5-1/program5-1# include# includemath.hmath.h float float cuberootcuberoot(floatfloat);); void mainvoid main(voidvoid) float p, q, float p, q, xrxr; coutcoutInput parameters Input parameters p,qp,q: : ; cincinp pq; q; float afloat asqrtsqrt (q/2) (q/2) * *(q/2) + (q/3) (q/2) + (q/3) * * (q/3) (q/

6、3) * * (q/3) ; (q/3) ; xrxrcuberootcuberoot(q q2 2a a)cuberootcuberoot(q q2 2a a);); coutcoutendlendlThe real root of the equation isThe real root of the equation isxrxr;float float cuberootcuberoot(float xfloat x) 5 5.1 5.1 三次方程求根程序的设计三次方程求根程序的设计 课本课本p129p129显示了不使用函数的程序。其中显示了不使用函数的程序。其中crootcroot 的

7、立方根的运的立方根的运算进行了两次算进行了两次, ,所以该计算程序要重复两次所以该计算程序要重复两次, , 当程序较长当程序较长, ,或计算或计算次数更多时,采用次数更多时,采用“子程序子程序”的方案可以大大缩短程序的长度。的方案可以大大缩短程序的长度。 特别是当程序比较复杂时,可以使得程序显得清晰,在特别是当程序比较复杂时,可以使得程序显得清晰,在program5_1 program5_1 中,中,mainmain()中不涉及计算立方根的细节,显得简()中不涉及计算立方根的细节,显得简洁,而在洁,而在cuberootcuberoot()中只解决一个浮点数的立方根的计算,也()中只解决一个浮点

8、数的立方根的计算,也很清楚。很清楚。 另外,还可以把立方根的计算与另外,还可以把立方根的计算与C+C+语言中的运算符和标准函数语言中的运算符和标准函数对应起来,当在程序中对于对应起来,当在程序中对于cuberootcuberoot(y y)给出了定义之后,就)给出了定义之后,就可以在主函数或其它用户定义的函数中,像运算符或标准函数那可以在主函数或其它用户定义的函数中,像运算符或标准函数那样使用了,如样使用了,如cuberootcuberoot(x x)的使用与)的使用与a+ba+b, sinsin(x x)的使用没)的使用没有什么区别。有什么区别。 65.2 5.2 函数的说明与使用函数的说明

9、与使用- - 参看书参看书p130p130的的5.25.2节节C+C+程序允许两种函数说明语句的形式,我们把它们分别称程序允许两种函数说明语句的形式,我们把它们分别称为函数原型(或函数声明)和函数定义。为函数原型(或函数声明)和函数定义。 n1 1函数原型函数原型n函数原型(亦称函数声明)用来指出函数的名称,类型和参函数原型(亦称函数声明)用来指出函数的名称,类型和参数,其格式为:数,其格式为:属性说明属性说明类型类型函数名函数名(参数表参数表);); intint add ( add (intint a, a, intint b); b); inline void swap (float &

10、amp; s, float & t);inline void swap (float & s, float & t); void print (char void print (char * *) ) ;75.2.1 5.2.1 函数的说明函数的说明 属性说明:可缺省,一般可以是下面的关键字之一:属性说明:可缺省,一般可以是下面的关键字之一:inlineinline,staticstatic,virtual, friend virtual, friend 等。等。inline inline 表示该函数为内联函数;表示该函数为内联函数;static static 表示该函

11、数为静态函数;表示该函数为静态函数;virtual virtual 表示该函数为虚函数;表示该函数为虚函数;friend friend 表示该函数为某类表示该函数为某类(class)(class)的友元函数。的友元函数。 类型:指函数的返回类型。类型:指函数的返回类型。 函数名:一个标识符。函数名:一个标识符。 参数表:它可能为空,参数表:它可能为空,void void 或或类型类型参数名参数名,类型类型参数参数名名 的形式。的形式。 main() main() ,print(voidprint(void) ) , cuberoot(floatcuberoot(float x) x) , ad

12、d(intadd(int a,inta,int b) b) 85.2.1 5.2.1 函数的说明函数的说明n 2 2函数定义函数定义n函数定义与函数原型的主要区别是它还包括函数体,函数定义与函数原型的主要区别是它还包括函数体,其格式为:其格式为: 属性说明属性说明类型类型函数名函数名(参数表参数表)函数体函数体 属性说明,返回类型,函数名与函数原型一致,参属性说明,返回类型,函数名与函数原型一致,参数表中不可省略参数名。数表中不可省略参数名。 函数体函数体:由和括起来的复合语句即程序块。由和括起来的复合语句即程序块。program 5_1 program 5_1 的最后的最后12 12 行就是

13、一个函数定义行就是一个函数定义。 9函数的分类方法函数的分类方法 1 1 从从使用角度使用角度分类分类 2 2 从从函数形式函数形式分类分类10 (1 1)从使用角度分类从使用角度分类 从从使用角度使用角度划分,可将函数分为:划分,可将函数分为:系统预定义系统预定义的标准库函数(如,的标准库函数(如,sinsin,absabs等),以及由等),以及由用户自用户自定义定义的函数。的函数。 程序中可直接使用(调用)系统预定义的标准程序中可直接使用(调用)系统预定义的标准库函数,但要求在调用前使用编译预处理指令库函数,但要求在调用前使用编译预处理指令includeinclude将对应的头文件包含进来

14、。将对应的头文件包含进来。 由用户自定义的函数与系统预定义的标准库函由用户自定义的函数与系统预定义的标准库函数的不同点在于,数的不同点在于,自定义函数的自定义函数的函数名函数名、参数个数参数个数、函数函数返回值类型返回值类型以及函数所实现的以及函数所实现的功能功能等都完全由等都完全由用户程序来规定(指定)用户程序来规定(指定)。11(2 2)从函数形式分类从函数形式分类 从从函数形式函数形式划分,可分为无参函数与有划分,可分为无参函数与有参函数两类。对参函数两类。对无参函数无参函数来说,调用它们时不来说,调用它们时不需要提供实际参数;而对需要提供实际参数;而对有参函数有参函数进行调用时,进行调

15、用时,必须提供所需个数的且具有相匹配数据类型的必须提供所需个数的且具有相匹配数据类型的实际参数。实际参数。12无参函数的定义无参函数的定义 。 无参函数定义无参函数定义的一般形式的一般形式 () () 1 . . n 通常用于通常用于实现某种固定功能实现某种固定功能。例如:。例如: void void printStarprintStar() . () . 就自定义了一个叫做就自定义了一个叫做printStarprintStar的无参函数,比的无参函数,比如可用它来实现打印出一行共如可用它来实现打印出一行共1010个个“* *”的固定功能的固定功能。13 有参函数定义有参函数定义的一般形式的一

16、般形式 ( ( ) 1 . . n 通过调用处提供的通过调用处提供的不同实参值不同实参值来来计算计算出其出其对应的函数值对应的函数值、或或实现某种与传递过来的那些不同值有关的某种功能实现某种与传递过来的那些不同值有关的某种功能。例如:。例如: void void printStar(intprintStar(int k) . k) . 就自定义了一个叫做就自定义了一个叫做printStarprintStar的具有的具有1 1个个intint型形参型形参k k的函的函数,比如可用它来实现打印出一行共数,比如可用它来实现打印出一行共k k个个“* *”的自定义功能。的自定义功能。145.2.2 5

17、.2.2 函数的调用函数的调用函数调用是已定义函数的一次实际运行,与某类型的一个函数调用是已定义函数的一次实际运行,与某类型的一个变量和后文中某类的一个对象类似变量和后文中某类的一个对象类似, ,函数调用是函数定义函数调用是函数定义的一个的一个“实例实例”。在在C+C+程序中,除程序中,除mainmain函数外,其它任函数外,其它任一函数的执行都是一函数的执行都是通过在通过在mainmain函数中直接或间接地调用该函数中直接或间接地调用该函数而引发函数而引发的。调用一个函数就是的。调用一个函数就是去执行该函数之函数体去执行该函数之函数体的过程。的过程。 对无参函数进行调用对无参函数进行调用的一

18、般形式为:的一般形式为: ()() 例如:例如:printStarprintStar(); (); 15 对有参函数进行调用对有参函数进行调用的一般形式为:的一般形式为: ( ( ) ) 例如:例如:printStar(26);printStar(26); 其中其中函数说明中的参数称为函数说明中的参数称为形式参数(形参形式参数(形参),函数调用中的参数称为,函数调用中的参数称为实际参数(实参实际参数(实参)。)。实参实参表表在在参数个数参数个数、参数顺序参数顺序、以及、以及参数类型参数类型等方面要等方面要与被调函数的与被调函数的形参表形参表之间有一个之间有一个一一对应一一对应的的相互匹相互匹配

19、配关系。编译器将根据参数的顺序,来逐一实现实关系。编译器将根据参数的顺序,来逐一实现实参与对应形参的参与对应形参的“结合结合”,而后执行一遍函数体(,而后执行一遍函数体(而完成本次的函数调用)。而完成本次的函数调用)。 16 计算机对计算机对函数进行调用函数进行调用的执行顺序的执行顺序以以Program5-1Program5-1为例为例(1) (1) 根据调用语句中的函数名根据调用语句中的函数名( (cuberootcuberoot) )在整个程序中搜索同名函数定在整个程序中搜索同名函数定义;义;(2) (2) 对实参数的参数个数,类型,顺序进行核对,判定是否与函数定义对实参数的参数个数,类型

20、,顺序进行核对,判定是否与函数定义中的形参表对应一致,在上例中只有一个浮点型参数;中的形参表对应一致,在上例中只有一个浮点型参数;(3) (3) 根据参数的类型(值参数或引用参数)进行值参数的值传递或引用根据参数的类型(值参数或引用参数)进行值参数的值传递或引用参数的换名,在上例中即是要把实参表达式的值计算出来赋给形参参数的换名,在上例中即是要把实参表达式的值计算出来赋给形参x x; (4) (4) 运行函数体代码;运行函数体代码;(5) (5) 返回调用点,并返回所要求的函数值,即返回计算结果返回调用点,并返回所要求的函数值,即返回计算结果crootcroot 的值。的值。17 关于关于函数

21、原型的一点说明函数原型的一点说明 当当函数调用从书写顺序上先于函数定义函数调用从书写顺序上先于函数定义时,时,C+C+要求必须事先列出这一函数的函数原型。要求必须事先列出这一函数的函数原型。 (1 1)无参函数)无参函数定义的函数原型定义的函数原型 () (); (2 2)有参函数)有参函数定义的函数原型定义的函数原型 ( ( ) ); 注意,与函数定义的一般形式相比,相当于用注意,与函数定义的一般形式相比,相当于用分号代换了函数体,而成为其相应的函数原型。分号代换了函数体,而成为其相应的函数原型。18 5.2.3 5.2.3 函数的返回函数的返回函数的返回完成两项任务:函数的返回完成两项任务

22、:n (1) (1) 把运行控制从函数体返回到函数调把运行控制从函数体返回到函数调用点。用点。 在在program5-1program5-1中就是在计算中就是在计算cuberootcuberoot (- (-q/2+a) q/2+a) 之后再返回到语句之后再返回到语句 xrxr = = cuberootcuberoot () + () + cuberootcuberoot () () 的的计算过程中。计算过程中。n(2) (2) 根据返回值要求,返回所需要的数根据返回值要求,返回所需要的数据值。据值。 19 5.2.3 5.2.3 函数的返回函数的返回n函数的返回值有下面几种情形:函数的返回值

23、有下面几种情形:n1.1.返回返回void void 类型类型 如果函数无值返回,应说明为如果函数无值返回,应说明为void void 类型。未作类型说明的函数,系统类型。未作类型说明的函数,系统认为是认为是intint 类型函数,应返回一整型值。类型函数,应返回一整型值。 n2 2返回数值类型返回数值类型 最常见的函数是返回一个数值的函数。最常见的函数是返回一个数值的函数。 例如:例如: intint add add(intint a a,intint b b);); 当函数要返回的数值不止一个时,情况比较复杂,一般它可以以结构或当函数要返回的数值不止一个时,情况比较复杂,一般它可以以结构或

24、类的形式,也可以以结构,数组或对象指针类型方式实现,这样的实例类的形式,也可以以结构,数组或对象指针类型方式实现,这样的实例在后面的章节可以见到。在后面的章节可以见到。n 3 3返回引用类型返回引用类型 值返回方式是值返回方式是C C 和和Pascal Pascal 语言中唯一的返回方式,语言中唯一的返回方式,C+C+语言提供的引语言提供的引用返回概念是一种很强的功能,当函数定义中把该函数说明为某类型的用返回概念是一种很强的功能,当函数定义中把该函数说明为某类型的引用类型时,该函数调用后返回的不单是值,而是包含返回值的变量引用类型时,该函数调用后返回的不单是值,而是包含返回值的变量(或对象)。

25、由于返回引用与引用类型有关,所以这样的实例将在下节(或对象)。由于返回引用与引用类型有关,所以这样的实例将在下节介绍。介绍。 20函数应用实例函数应用实例1. 1. 实例实例1 - 1 - 无须给出函数无须给出函数f f的原型的原型 设设 f(x) = (xf(x) = (x* *x+x+1)/2-5.5x+x+1)/2-5.5。(1 1)求求z = (f(2.5)+2z = (f(2.5)+2* *f(6)/f(4.3)f(6)/f(4.3),并显示结果并显示结果z z。(2 2)对任意输入的一个实数对任意输入的一个实数a a,求出求出f(a)f(a)并显示。并显示。 程序执行后的交互结果如

26、下:程序执行后的交互结果如下:z=4.90618z=4.90618Input a=Input a=1010f(a)=50f(a)=5021程序编制:程序编制:# #include include double f (double x)double f (double x)double y;double y;y=(xy=(x* *x+x+1)/2-5.5;x+x+1)/2-5.5;return (y); return (y); / /对非对非voidvoid类型的函数,必须有一个类型的函数,必须有一个 /return /return语句,由它返回函数值语句,由它返回函数值 22void main

27、()void main()double z,a;double z,a;z=(f(2.5)+2z=(f(2.5)+2* *f(6)/f(4.3); /f(6)/f(4.3); /调用自定义函数调用自定义函数f fcoutcoutz=zz=zendlendl; ;coutcoutInput a=; a;a;coutcoutf(a)=f(a)f(a)=f(a)endlendl; /; /算出算出f(a)f(a)并输出并输出 23点评:点评: 1 1)mainmain中共出现了中共出现了4 4次对自定义函数次对自定义函数f f的调用。的调用。 2 2)编写编写f f函数时的函数时的3 3点注意:点注意

28、: (1 1)f f函数体内的函数体内的3 3行也可用如下的一行来代替行也可用如下的一行来代替 return (xreturn (x* *x+x+1)/2-5.5); x+x+1)/2-5.5); return return句括号内表达式的值,即为整个函数的返句括号内表达式的值,即为整个函数的返回值。回值。 (2 2)returnreturn句也可使用另一格式,即可以不括起句也可使用另一格式,即可以不括起表达式:表达式: return (xreturn (x* *x+x+1)/2-5.5; /OK!x+x+1)/2-5.5; /OK!24(3 3)三种不正确的用法三种不正确的用法 f=(xf=

29、(x* *x+x+1)/2-5.5;x+x+1)/2-5.5; 不可给函数名不可给函数名f f赋值。赋值。 return (f);return (f); 返回值类型应该是返回值类型应该是doubledouble,而非指针类型(函而非指针类型(函数名相当于一个指针)。数名相当于一个指针)。 f(x)=(xf(x)=(x* *x+x+1)/2-5.5;x+x+1)/2-5.5; 赋值号左端非变量(也即赋值号左端非变量(也即f(x)f(x)非左值)。非左值)。 25 3 3)关于关于returnreturn语句语句returnreturn语句(称为返回语句)具有如下三种使用格式:语句(称为返回语句)

30、具有如下三种使用格式:return;return;return return ;return ( return ( ); );第一种第一种格式的格式的returnreturn用于立即从被调函数中返回用于立即从被调函数中返回, , 当函当函数数类型为类型为voidvoid时,应使用这种格式的返回语句。时,应使用这种格式的返回语句。 当函数当函数类型为非类型为非voidvoid型时,应使用型时,应使用第二或第三种第二或第三种格式的格式的returnreturn语句,此两种格式的语句效果完全相同(可将第二种语句,此两种格式的语句效果完全相同(可将第二种格式看成是第三种格式的省略形式),系统此时都将计

31、算出格式看成是第三种格式的省略形式),系统此时都将计算出表达式的值,并表达式的值,并“携带携带”该值立即从被调函数中返回。该值立即从被调函数中返回。26 2. 2. 实例实例2 - 2 - mainmain在前而被调函数在前而被调函数f f 在后时,必须先列出函数在后时,必须先列出函数f f的原型的原型 设设 f(x) = (xf(x) = (x* *x+x+1)/2-5.5x+x+1)/2-5.5。 (1 1)求求z = (f(2.5)+2z = (f(2.5)+2* *f(6)/f(4.3)f(6)/f(4.3),并显示结果并显示结果z z。 (2 2)对任意输入的一个实数对任意输入的一个

32、实数a a,求出求出f(a)f(a)并显示。并显示。 程序执行后的交互结果如下:程序执行后的交互结果如下:z=4.90618z=4.90618Input a=Input a=1010f(a)=50f(a)=5027程序编制:程序编制:# #include include double f (double x); double f (double x); /函数函数f f的原型的原型 void main()void main() /同上,从略同上,从略 double f (double x) double f (double x) /被调函数被调函数f f的具体定义的具体定义 /同上,从略同上,

33、从略 283. 3. 实例实例3 - 3 - 无参函数,实现固定功能无参函数,实现固定功能 编无参函数,编无参函数,void void printStarprintStar()(),它负责它负责完成完成固定功能固定功能:在同一行连续显示:在同一行连续显示6060个个“* *”。并编制。并编制主函数主函数mainmain,对该函数实现调用,使程序执行后的对该函数实现调用,使程序执行后的显示结果如下:显示结果如下:the result of first call to the result of first call to printStarprintStar():():* * * * * * *

34、 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *the result of second call to the result of second call to printStarprintStar():():* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

35、* * * * * * 29程序编制:程序编制: # #include include void void printStarprintStar() () /自定义无参函数自定义无参函数printStarprintStarfor(intfor(int i=1; i=60; i+) / i=1; i=60; i+) /显示显示6060个个“* *”coutcout* *;coutcoutendlendl; ;return; return; 30 void main()coutthe result of first call to printStar():endl;printStar();/对对p

36、rintStar的第一次调用的第一次调用coutthe result of second call to printStar():endl;printStar();/对对printStar的第二次调用的第二次调用 31点评:点评: (1 1)将将printStarprintStar定为定为voidvoid类型类型,是因为,是因为不需要它返回不需要它返回任何值任何值。(2 2)按语句方式调用按语句方式调用printStarprintStar(而不可作为表达式因而不可作为表达式因子,如子,如3+3+printStar()/2printStar()/2等)。等)。(3 3)printStarprin

37、tStar函数中的函数中的returnreturn用于立即从被调函数中用于立即从被调函数中返回到主调函数处(跳转到调用语句的下一语句处)去执返回到主调函数处(跳转到调用语句的下一语句处)去执行,当函数类型为行,当函数类型为voidvoid时,应使用这种无返回值的时,应使用这种无返回值的returnreturn语句。实际上,由于本函数是语句。实际上,由于本函数是在执行完函数体内的所有语在执行完函数体内的所有语句后才返回句后才返回,此种情况下的,此种情况下的returnreturn语句可以缺省语句可以缺省。32 4. 4. 实例实例4 - 4 - 一参函数一参函数 编一参函数,编一参函数,void

38、 void printStar(intprintStar(int k) k),它它负责负责显示出显示出k k行行“* *”来,其中每行均显示连续的来,其中每行均显示连续的8 8个个“* *”。并编制主函数。并编制主函数mainmain,对该函数实现调用,对该函数实现调用,使程序执行后的显示结果样式如下:使程序执行后的显示结果样式如下:k=? k=? 3 3* * * * * * * * * * * * * * * * * * * * * * * * *33程序编制:程序编制:#include void printStar(int k) /k/k为形参,由调用处的实参提供实际值为形参,由调用处的

39、实参提供实际值for(int i=1; i=k; i+) /显示出显示出k k行行 cout*endl;return; /该该returnreturn语句可以缺省语句可以缺省 void main()int k; /欲显示的行数欲显示的行数k kcoutk;printStar(k); /函数调用,带去输入的实参函数调用,带去输入的实参k k 34 5. 5. 实例实例5 - 5 - 二参函数二参函数 编二参函数,编二参函数,void void printStar(intprintStar(int k, k, intint n)n),它负责它负责显示出显示出k k行行“* *”来,且来,且每行每行

40、均均显示显示连续的连续的n n个个“* *”。并编制主函数,对该函数实。并编制主函数,对该函数实现调用,使程序执行后的显示结果样式如下:现调用,使程序执行后的显示结果样式如下:k,n=? k,n=? 4 154 15* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *35程序编制:程序编制:#include void printStar(int k, int n) /负责显示出负责显示出k行行*来,且每行均

41、显示连续的来,且每行均显示连续的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()void main()intint k,n; / k,n; /显示出显示出k k行,每行显示行,每行显示n n个个“* *”coutcoutk,n=? ;kn; kn; printStar(kprintStar(k, n); ,

42、n); / /以输入的以输入的k k与与n n为实参去调用为实参去调用printStarprintStar 37 6. 6. 实例实例6 - 6 - 无参函数,全局变量无参函数,全局变量 编无参函数,编无参函数,void void printStarprintStar()(),并并结合使结合使用全局变量用全局变量k k与与n n,使每调用一次该函数,总使每调用一次该函数,总显示显示出出k k行行“* *”来,且来,且每行每行均均显示显示连续的连续的n n个个“* *”,并编制主函数,对该函数实现调用,使程序执行并编制主函数,对该函数实现调用,使程序执行后的显示结果样式如下:后的显示结果样式如下

43、:k,n=? k,n=? 3 203 20* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 38程序编制:程序编制: # #include include intint k,n; k,n; /intint型型全局变量全局变量k k,n n / /* * 在在所有函数之外所有函数之外(即在不属于任一函数定义的外(即在不属于任一函数定义的外面)面)说明的变量为说明的变量为全局变量全局变量,其作用域即有效区域

44、,其作用域即有效区域为整个文件(或具有多个文件的整个程序,详细请为整个文件(或具有多个文件的整个程序,详细请参看本章的参看本章的5.75.7及及5.85.8节)。节)。 * */ /39void void printStarprintStar() /() /无参函数无参函数printStarprintStar /其中所用的其中所用的k k与与n n都是全局变量都是全局变量for(intfor(int i=1; i=k; i+) i=1; i=k; i+)/显示出显示出k k行行“* *” ” for(intfor(int j=1; j=n; j+) j=1; j=n; j+) /显示显示n n

45、个个“* *” ” coutcout* *; coutcoutendlendl; ; 40void main()coutkn;/输入全局变量输入全局变量k,全局变量全局变量n的值的值coutthe result of call to printStar():endl;printStar(); /调用无参函数调用无参函数printStar 415.5.2.4 2.4 函数的参数函数的参数 C+C+语言允许函数无参,有一个或多个参数,而且还支持不定个数参数的函数。语言允许函数无参,有一个或多个参数,而且还支持不定个数参数的函数。 (1)(1)无参函数:用无参函数:用void void 或空表示无参

46、。或空表示无参。 (2)(2)一个或多个参数:多数函数有一个或多个确定的个数、确定的类型和顺序的参一个或多个参数:多数函数有一个或多个确定的个数、确定的类型和顺序的参数。数。 在在C+C+语言中,不同的函数是根据函数名和参数表二者来区分的,只有二者语言中,不同的函数是根据函数名和参数表二者来区分的,只有二者完全一致才是同一函数。完全一致才是同一函数。 (3 3)不定个数参数:)不定个数参数: 有些应用问题中参数个数是变化的。有些应用问题中参数个数是变化的。 例如设计一个电话计费函数,为了计算通话费,不同的通话类型(如市话,例如设计一个电话计费函数,为了计算通话费,不同的通话类型(如市话,长途,

47、数据与通讯,长途,数据与通讯,BP BP 机等)有不同数目的参数。机等)有不同数目的参数。 处理参数个数不定的情形,可有不同的途径:处理参数个数不定的情形,可有不同的途径:例如指针,例如指针,C+C+提供的某些库函数,提供的某些库函数,无名参数,可缺省参数等。无名参数,可缺省参数等。 42 无名参数无名参数 -n C+ C+ 语言语言, ,允许参数表中包含无名参数,主要是允许参数表中包含无名参数,主要是为了区分函数,为了区分函数, 例如:例如: intint f f(intint a a,intint b b)return areturn ab b* *b b; intint f f(inti

48、nt a a,intint b b,intint)return areturn a* *a ab b; 两个不同的函数同名,但由于第二个函数包含一无两个不同的函数同名,但由于第二个函数包含一无名参数,使得在调用时能够被区分,名参数,使得在调用时能够被区分,f f(x x,y y)是第)是第一个函数的调用,一个函数的调用,f f(x x,y y,0 0)是第二个函数的调)是第二个函数的调用。用。43 可缺省参数(参数默认值)可缺省参数(参数默认值) - 允许在允许在函数定义处函数定义处为其中为其中最后面的连续若干个参数最后面的连续若干个参数设置设置默认值默认值(也称(也称缺省值缺省值),从而为调

49、用处提供了方便(若调用),从而为调用处提供了方便(若调用处缺省了某个或某些实参的情况下,系统将自动使用那些在处缺省了某个或某些实参的情况下,系统将自动使用那些在函数定义处给定的参数默认值)。函数定义处给定的参数默认值)。 下面是一个示例性程序,在定义函数下面是一个示例性程序,在定义函数funcfunc时为它的最后时为它的最后面的连续面的连续3 3个参数(也即它的所有参数)都设置了默认值。若个参数(也即它的所有参数)都设置了默认值。若调用处缺省调用处缺省了某个或某些了某个或某些实参实参的情况下,系统将的情况下,系统将自动使用自动使用这这些给定的参数些给定的参数默认值默认值。44#include

50、void func(int a=11, int b=22, int c=33) /为参数为参数a、b、c设置了默认值设置了默认值11、22与与33couta=a, b=b, c=cendl; 45void main()void main() funcfunc();(); / /调用时调用时缺省了缺省了3 3个实参个实参,将使用,将使用 / /定义处给定的那定义处给定的那3 3个相对应的参数默认值个相对应的参数默认值 func(55);func(55); / /调用时调用时缺省了后缺省了后2 2个实参个实参,将使用,将使用 / /定义处给定的那后定义处给定的那后2 2个对应参数默认值个对应参数默

51、认值 func(77,99);func(77,99); / /调用时调用时缺省了最后缺省了最后1 1个实参个实参,将使用,将使用 / /定义处给定的那最后定义处给定的那最后1 1个参数默认值个参数默认值 func(8,88,888);func(8,88,888); / /调用时调用时没缺省任一个实参没缺省任一个实参,系统将,系统将 / /不使用定义处给定的任一个参数默认值不使用定义处给定的任一个参数默认值 46程序执行后的显示结果如下:程序执行后的显示结果如下: a=11, b=22, c=33a=11, b=22, c=33a=55, b=22, c=33a=55, b=22, c=33a=

52、77, b=99, c=33a=77, b=99, c=33a=8, b=88, c=888a=8, b=88, c=88847 注意,只能为函数注意,只能为函数最后面的连续若干个最后面的连续若干个参数设置默认值,且在参数设置默认值,且在调用处调用处也只能缺省也只能缺省后面的连续若干个后面的连续若干个实参。实参。 void void func(intfunc(int a, a, intint b=2, b=2, intint c=3); c=3); /OK!/OK! void void func(intfunc(int a=1, a=1, intint b, b, intint c=3); c

53、=3); /ERROR!/ERROR! 对第一个函数说明,采用如下的调用语句:对第一个函数说明,采用如下的调用语句: func(1, 22, 333); func(1, 22, 333); /OK! /OK! 调用时给出所有实参调用时给出所有实参 funcfunc(); (); / ERROR! / ERROR! 参数参数a a没有默认值没有默认值 func(10, 20); func(10, 20); /OK! /OK! 参数参数c c默认为默认为3 3 func(5, , 9); func(5, , 9); / ERROR! / ERROR! 调用处也只能缺省后面的连续若干个实参调用处也只

54、能缺省后面的连续若干个实参 485.5.2.5 2.5 值调用和引用调用值调用和引用调用C+C+语言在进行函数调用时,对参数的处理有两种方式,赋语言在进行函数调用时,对参数的处理有两种方式,赋值型和引用型,即值调用方式和引用调用方式。前者是普通的形值型和引用型,即值调用方式和引用调用方式。前者是普通的形式,在式,在C C 语言中只有这种方式;语言中只有这种方式;C+C+语言中增加了引用调用形式,语言中增加了引用调用形式,这种形式与这种形式与pascalpascal 语言中的变量参数调用方式相似。语言中的变量参数调用方式相似。 1 1 赋值调用赋值调用2 2 引用调用引用调用 49赋值调用赋值调

55、用 - -赋值形参:在函数定义的参数中,除了被说明为引用(赋值形参:在函数定义的参数中,除了被说明为引用(& &)的参数之外,其)的参数之外,其余所有类型的形参都属于赋值形参。余所有类型的形参都属于赋值形参。过程:过程:在执行函数调用时,在检查函数名及参数表之后,首先为值参数分在执行函数调用时,在检查函数名及参数表之后,首先为值参数分配内存,然后计算各对应的实参表达式,并把计算的值赋给刚刚创建的配内存,然后计算各对应的实参表达式,并把计算的值赋给刚刚创建的参数变量,进而开始函数体的运行。参数变量,进而开始函数体的运行。 凡是赋值形参,在函数的每次调用时,凡是赋值形参,在函数的每

56、次调用时,都必须为每一个赋值形参创建一个都必须为每一个赋值形参创建一个新的参数变量。新的参数变量。n实参表达式:另一方面,函数调用语句中,与赋值形参相对应的实参可实参表达式:另一方面,函数调用语句中,与赋值形参相对应的实参可以是指定类型的常量、变量或表达式。在执行函数调用时应把该表达式以是指定类型的常量、变量或表达式。在执行函数调用时应把该表达式的值计算出来,作为初值赋给刚刚为赋值形参创建的参数变量。这是赋的值计算出来,作为初值赋给刚刚为赋值形参创建的参数变量。这是赋值调用方式名称的由来。值调用方式名称的由来。n为赋值形参创建的参数变量是局限于函数体运行的局部变量,它作为该为赋值形参创建的参数

57、变量是局限于函数体运行的局部变量,它作为该形参的一个实例,参加函数体程序块的这次运行,形参的一个实例,参加函数体程序块的这次运行,一旦运行完毕,这个一旦运行完毕,这个参数变量就被撤消参数变量就被撤消。 50引用调用引用调用函数定义的参数表中,名字前加上符号的参数为引用形参。函数定义的参数表中,名字前加上符号的参数为引用形参。 n例如例如void swapvoid swap(intint a a,intint b b););引用形参在调用过程中的参数传递机制不同于赋值形参。其要点是:引用形参在调用过程中的参数传递机制不同于赋值形参。其要点是:(1 1)函数的调用语句中对应于引用形参的实参必须是同

58、一类型的变量,非)函数的调用语句中对应于引用形参的实参必须是同一类型的变量,非变量的表达式则不允许。变量的表达式则不允许。(2 2)参数传递的内容不是实参的值,而是地址,其实际的效果是令对应的)参数传递的内容不是实参的值,而是地址,其实际的效果是令对应的引用形参在调用过程中,作为一个变量名指向作为实参的这个变量,引用形参在调用过程中,作为一个变量名指向作为实参的这个变量,与赋值形参的不同在这里体现出来,在引用调用过程中并不创建新的与赋值形参的不同在这里体现出来,在引用调用过程中并不创建新的参数变量!参数变量!(3 3)在函数体程序块的运行中,引用形参的每次出现,由于它现在已经是)在函数体程序块

59、的运行中,引用形参的每次出现,由于它现在已经是指向实参变量,因此相当于全用实参变量所代替。即起到了所谓的指向实参变量,因此相当于全用实参变量所代替。即起到了所谓的“换名换名”的作用。的作用。(4 4)在函数体程序运行结束,控制转回调用点时,该引用形参与实参变量)在函数体程序运行结束,控制转回调用点时,该引用形参与实参变量的对应关系也就终止了。但是在调用过程中对于这个实参变量的所有的对应关系也就终止了。但是在调用过程中对于这个实参变量的所有处理和操作的结果,却保留下来。这一点也是区别于赋值调用的。处理和操作的结果,却保留下来。这一点也是区别于赋值调用的。 51引用调用引用调用n设计函数在下面两种

60、情形时,设计函数在下面两种情形时, 需要改变某些变量的值(上述函数需要改变某些变量的值(上述函数swap swap 就是一就是一例);例); 对于占内存较多的数据参数,为了不另建新的参对于占内存较多的数据参数,为了不另建新的参数变量以节省内存,建议采用引用参数。数变量以节省内存,建议采用引用参数。 在后一种情况,为了保证实参不在函数中被修改,在后一种情况,为了保证实参不在函数中被修改,可在形参说明中加上可在形参说明中加上const const 说明,例如:说明,例如: complex add complex add(const complexconst complex a a,const complexconst complex b b);); 而对于赋值形参,则无此必要。而对于赋值形参,则无此必要。52实

温馨提示

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

评论

0/150

提交评论