《【教学课件】第6章过程封装-函数.ppt》由会员分享,可在线阅读,更多相关《【教学课件】第6章过程封装-函数.ppt(136页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、程序设计 cs.sjtu 2011.9程序设计-1第第6章章 过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2011.9程序设计-2函数的用途函数的用途v函数是程序设计语言中最重要的部分,是模块函数是程序设计语言中最重要的部分,是模块化设计的主要工具。每一个化设计的主要工具。每一个C+程序都要用到程序都要用到函数。函数。v
2、即使你自己不定义新的函数即使你自己不定义新的函数,在每一个完整的在每一个完整的C+程序中都必须有一个程序中都必须有一个main()函数。函数。v在在C+语言中,字符处理、字符串处理和数学语言中,字符处理、字符串处理和数学计算都是用函数的方式提供的。计算都是用函数的方式提供的。程序设计 cs.sjtu 2011.9程序设计-3第第6章章 过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归
3、函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2011.9程序设计-4如何写一个函数如何写一个函数v函数定义函数定义v函数的返回值:返回值类型应与定义中的类型标识符函数的返回值:返回值类型应与定义中的类型标识符一致。一致。C+的函数只能有一个返回值。的函数只能有一个返回值。v表示一个函数没有返回值,类型标识符用表示一个函数没有返回值,类型标识符用void。没有。没有返回值的函数也称为过程返回值的函数也称为过程类型标识符类型标识符函数名(形式参数表)函数名(形式参数表)变量定义部分变量定义部分语句部分语句部分return返回值;返回值;或或return(返回值);(返回值);eg.
4、intmax(inta,intb)if(ab)return(a)elsereturn(b);函数体函数体程序设计 cs.sjtu 2011.9程序设计-5函数的命名函数的命名v函数名是一个标识符,符合标识符命名函数名是一个标识符,符合标识符命名规范规范v函数名要有意义函数名要有意义v函数名一般是一个动词短语,表示函数函数名一般是一个动词短语,表示函数的行为的行为程序设计 cs.sjtu 2011.9程序设计-6函数举例函数举例无参数、无返回值的函数无参数、无返回值的函数 v打印一个由五行组成的三角形打印一个由五行组成的三角形*voidprintstar()cout“*n”;cout“*n”;c
5、out“*n”;cout“*n”;cout“*n”;程序设计 cs.sjtu 2011.9程序设计-7函数举例函数举例有参数、无返回值的函数有参数、无返回值的函数v打印一个由打印一个由n行组成的三角形行组成的三角形void printstar(int numOfLine)int i,j;for(i=1;i=numOfLine;+i)cout endl;for(j=1;j=numOfLine-i;+j)cout ;for(j=1;j=2*i-1;+j)cout num;if(num=1&num=10)returnnum;程序设计 cs.sjtu 2011.9程序设计-9函数举例函数举例有参数、有
6、返回值的函数有参数、有返回值的函数 v计算计算n!intp(intn)ints=1,i;if(n0)return(0);for(i=1;i=n;+i)s*=i;return(s);程序设计 cs.sjtu 2011.9程序设计-10函数举例函数举例返回布尔量的函数返回布尔量的函数v判断某一年是否为润年的函数判断某一年是否为润年的函数bool IsLeapYear(int year)bool leapyear;leapyear=(year%4=0)&(year%100!=0)|(year%400=0);return(leapyear);程序设计 cs.sjtu 2011.9程序设计-11第第6章
7、章 过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2011.9程序设计-12函数的声明函数的声明v所有函数在使用前必须被声明,以便让编译器知道所有函数在使用前必须被声明,以便让编译器知道用户的用法是否正确。用户的用法是否正确。v函数声明包括下列内容:函数声明包括下列内容:函数名函数名函数的参数类型函数的参数类型函数的返回类
8、型函数的返回类型v函数的声明被称为函数的原型,它的形式为:函数的声明被称为函数的原型,它的形式为:返回类型返回类型函数名(参数表);函数名(参数表);参数表中的每个参数说明可以是类型,也可以是类参数表中的每个参数说明可以是类型,也可以是类型后面再接一个参数名。如:型后面再接一个参数名。如:intmax(int,int);intmax(inta,intb);程序设计 cs.sjtu 2011.9程序设计-13函数说明规则函数说明规则v库函数在调用前需要库函数在调用前需要include相应的头文件。相应的头文件。v自定义的函数在调用时需要进行函数原型说明。自定义的函数在调用时需要进行函数原型说明。
9、v函数原型说明与函数首部写法上需要保持一致,函数原型说明与函数首部写法上需要保持一致,即函数类型、函数名、参数个数和参数顺序必即函数类型、函数名、参数个数和参数顺序必须相同。须相同。v如果被调函数的定义在主调函数之前,可以不如果被调函数的定义在主调函数之前,可以不必加声明。必加声明。v如果在所有函数定义之前,在函数外部已经做如果在所有函数定义之前,在函数外部已经做了函数声明,则在主调函数中无须再作声明。了函数声明,则在主调函数中无须再作声明。程序设计 cs.sjtu 2011.9程序设计-14函数调用函数调用#includeintmax(inta,intb);main()intx,y;cinx
10、y;coutb)return(a);elsereturn(b);函数原型说明函数原型说明函数调用函数调用函数实现函数实现程序设计 cs.sjtu 2011.9程序设计-15函数调用函数调用#includeintmax(inta,intb)if(ab)return(a);elsereturn(b);main()intx,y;cinxy;cout x y;cout max(x,y);int p(int n)int s=1,i;if(n 0)return(0);for(i=1;in2?n1:n2);mainx(2)y(3)mainx(2)y(3)maxa(2)b(3)n1n2mainx(2)y(3)
11、maxa(2)b(3)n1n2pn(2)simainx(2)y(3)maxa(2)b(3)n1(2)n2pn(3)simainx(2)y(3)maxa(2)b(3)n1(2)n2(6)mainx(2)y(3)程序设计 cs.sjtu 2011.9程序设计-20第第6章章 过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模板函数模板v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 201
12、1.9程序设计-21数组作为函数的参数数组作为函数的参数v设计一函数,统计设计一函数,统计10位同学的平均成绩位同学的平均成绩v设计考虑:如何传递参数设计考虑:如何传递参数参数是参数是10位同学的考试成绩,可以用位同学的考试成绩,可以用10个整型数个整型数来表示。所以有来表示。所以有10个整型的形式参数个整型的形式参数一组同类数据可以用一个数组来描述,所以参数一组同类数据可以用一个数组来描述,所以参数也可以是一个也可以是一个10个元素的整型数组个元素的整型数组第二种方法更加简练第二种方法更加简练返回值是平均成绩返回值是平均成绩程序设计 cs.sjtu 2011.9程序设计-22统计函数的实现统
13、计函数的实现intaverage(intarray10)inti,sum=0;for(i=0;i10;+i)sum+=arrayi;returnsum/10;程序设计 cs.sjtu 2011.9程序设计-23average函数的使用函数的使用intmain()inti,score10;cout请输入请输入10个成绩:个成绩:endl;for(i=0;iscorei;cout平均成绩是:平均成绩是:average(score)endl;return0;注意:形式参数是注意:形式参数是数组,实际参数也数组,实际参数也是一个数组是一个数组程序设计 cs.sjtu 2011.9程序设计-24一个有趣
14、的现象一个有趣的现象 v在函数在函数average的的return语句前增加一个对语句前增加一个对array3赋值的语句,如赋值的语句,如array3=90。v在在main函数的函数的average函数调用后,即函数调用后,即return语句前增加一个输出语句前增加一个输出score3的语句的语句v结果是什么?结果是什么?v你会发现输出的值你会发现输出的值90而不是而不是80。程序设计 cs.sjtu 2011.9程序设计-25数组参数的传递机制数组参数的传递机制vC+语言规定,数组名是数组的起始地址语言规定,数组名是数组的起始地址v参数传递时,实际参数是数组名,形式参数也是数参数传递时,实际
15、参数是数组名,形式参数也是数组名组名v按照值传递,当用实际参数按照值传递,当用实际参数score调用函数调用函数average时,是用时,是用score初始化形式参数数组初始化形式参数数组array。如。如score的首地址为的首地址为1000,在函数中形参数组,在函数中形参数组array的的首地址也为首地址也为1000。v形式参数和实际参数是同一数组!形式参数和实际参数是同一数组!程序设计 cs.sjtu 2011.9程序设计-26数组作为函数的参数数组作为函数的参数v在函数中并没有定义新的数组在函数中并没有定义新的数组v对形式参数数组指定规模是没有意义的对形式参数数组指定规模是没有意义的v
16、形式参数数组不需要指定大小,所以方括号中形式参数数组不需要指定大小,所以方括号中为空为空v函数如何知道数组的规模?用另一个整型参数函数如何知道数组的规模?用另一个整型参数表示表示v总结:数组传递需要两个参数,数组名和数组总结:数组传递需要两个参数,数组名和数组规模规模程序设计 cs.sjtu 2011.9程序设计-27第第6章章 过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v
17、基于递归的算法基于递归的算法程序设计 cs.sjtu 2011.9程序设计-28默认参数默认参数v对于某些函数,程序往往会用一些固定的值去调用它对于某些函数,程序往往会用一些固定的值去调用它.例例如对于以某种数制输出整型数的函数如对于以某种数制输出整型数的函数print:voidprint(intvalue,intbase);在大多数情况下都是以十进制输出,因此在大多数情况下都是以十进制输出,因此base的值总是的值总是为为10。vC+在定义或声明函数时可以为函数的某个参数指定默认在定义或声明函数时可以为函数的某个参数指定默认值。当调用函数时没有为它指定实际参数时,系统自动值。当调用函数时没有
18、为它指定实际参数时,系统自动将默认值赋给形式参数。例如,可以将将默认值赋给形式参数。例如,可以将print函数声明为函数声明为voidprint(intvalue,intbase=10);调用调用print(20)等价于等价于print(20,10)程序设计 cs.sjtu 2011.9程序设计-29带有默认参数的函数的使用带有默认参数的函数的使用 C+C+在说明函数原型时,可以为一个或多个参在说明函数原型时,可以为一个或多个参数指定缺省值。调用此函数时,若缺省某一参数指定缺省值。调用此函数时,若缺省某一参数,数,C+C+自动以缺省值作为此参数的值。如:自动以缺省值作为此参数的值。如:int
19、special(int x=2,float y=1.5)int special(int x=2,float y=1.5)调用时可用:调用时可用:special(5,3.2)/x=5;y=3.2special(5,3.2)/x=5;y=3.2 special(6)/x=6;y=1.5 special(6)/x=6;y=1.5 special()/x=2;y=1.5 special()/x=2;y=1.5程序设计 cs.sjtu 2011.9程序设计-30带有默认参数的函数带有默认参数的函数注意事项注意事项v缺省参数无论有几个,都必须放在参数序列缺省参数无论有几个,都必须放在参数序列的最后,的最后
20、,例如:例如:Int SaveName(char*first,char Int SaveName(char*first,char second=second=“”,char*third=,char*third=“”,char,char*fouth=*fouth=“”););v在函数调用时,若某个参数省略,则其后的在函数调用时,若某个参数省略,则其后的参数皆应省略而取其缺省值参数皆应省略而取其缺省值程序设计 cs.sjtu 2011.9程序设计-31带有默认参数的函数带有默认参数的函数注意事项注意事项v对参数默认值的指定只有在函数声明处有意义。对参数默认值的指定只有在函数声明处有意义。因为函数的
21、默认值是提供给调用者使用的。因为函数的默认值是提供给调用者使用的。v在不同的源文件中,可以对函数的参数指定不同在不同的源文件中,可以对函数的参数指定不同的默认值。例如对于上面的的默认值。例如对于上面的print函数,如果在某函数,如果在某一个功能模块中输出的大多是十进制数,那么在一个功能模块中输出的大多是十进制数,那么在此功能对应的源文件中可以指定此功能对应的源文件中可以指定base的默认值为的默认值为10。如果在另一个功能最模块中经常要以二进制。如果在另一个功能最模块中经常要以二进制输出,那么在此功能模块对应的源文件中可以指输出,那么在此功能模块对应的源文件中可以指定默认值是定默认值是2。程
22、序设计 cs.sjtu 2011.9程序设计-32第第6章章 过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2011.9程序设计-33内联函数内联函数v目的是为了提高执行效率。目的是为了提高执行效率。v对于任何内联函数,编译器在符号表里放入函对于任何内联函数,编译器在符号表里放入函数的声明(包括名字、参数类型、返回值类型)
23、数的声明(包括名字、参数类型、返回值类型)。如果编译器没有发现内联函数存在错误,那。如果编译器没有发现内联函数存在错误,那么该函数的代码也被放入符号表里。在调用内么该函数的代码也被放入符号表里。在调用内联函数时,编译器直接用内联函数的代码替换联函数时,编译器直接用内联函数的代码替换函数调用,于是省去了函数调用的开销。函数调用,于是省去了函数调用的开销。程序设计 cs.sjtu 2011.9程序设计-34内联函数内联函数v内联函数的定义:在函数头部前加保留词内联函数的定义:在函数头部前加保留词inline#includeinlinefloatcube(floats)returns*s*s;int
24、main()floatside;cinside;coutcube(side)endls;return0;程序设计 cs.sjtu 2011.9程序设计-35慎用内联函数慎用内联函数v内联以代码复制内联以代码复制(膨胀膨胀)为代价,省去了函数调为代价,省去了函数调用的开销,提高函数的执行效率。如果相比用的开销,提高函数的执行效率。如果相比于执行函数体内代码的时间,函数调用的开于执行函数体内代码的时间,函数调用的开销可以忽略不计,那么效率的收获会很小。销可以忽略不计,那么效率的收获会很小。v以下情况不宜用内联以下情况不宜用内联:如果函数体内的代码比较长,使用内联将导致如果函数体内的代码比较长,使用
25、内联将导致内存消耗代价较高。内存消耗代价较高。如果函数体内出现循环,那么执行函数体内代如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。码的时间要比函数调用的开销大。程序设计 cs.sjtu 2011.9程序设计-36第第6章章 过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2011.9程序设计-37重
26、载函数重载函数v在传统的在传统的C语言中,不允许出现同名函数。当要语言中,不允许出现同名函数。当要求写一组功能类似、参数类型或参数个数不同求写一组功能类似、参数类型或参数个数不同的函数时,必须给它们取不同的函数名的函数时,必须给它们取不同的函数名v例如某个程序要求找出一组数据中的最大值,例如某个程序要求找出一组数据中的最大值,这组数据最多有这组数据最多有5个数据。我们必须写四个函数:个数据。我们必须写四个函数:求两个值中的最大值、求三个值中的最大值、求两个值中的最大值、求三个值中的最大值、求四个值中的最大值和求五个值中的最大值。求四个值中的最大值和求五个值中的最大值。我们必须为这四个函数取四个
27、不同的函数名,我们必须为这四个函数取四个不同的函数名,例如:例如:max2,max3,max4和和max5。程序设计 cs.sjtu 2011.9程序设计-38函数重载函数重载v使参数个数不同、参数类型不同或两者兼使参数个数不同、参数类型不同或两者兼而有之的两个以上的函数取相同的函数名而有之的两个以上的函数取相同的函数名v如如intmax(inta1,inta2);intmax(inta1,inta2,inta3);intmax(inta1,inta2,inta3,inta4);intmax(inta1,inta2,inta3,inta4,inta5);程序设计 cs.sjtu 2011.9程
28、序设计-39函数重载的实现函数重载的实现v由编译器确定某一次函数调用到底是调用了哪一由编译器确定某一次函数调用到底是调用了哪一个具体的函数。这个过程称之为绑定(个具体的函数。这个过程称之为绑定(binding,又称为联编或捆绑)。又称为联编或捆绑)。v编译器首先会为这一组重载函数中的每个函数取编译器首先会为这一组重载函数中的每个函数取一个不同的内部名字。当发生函数调用时,编译一个不同的内部名字。当发生函数调用时,编译器根据实际参数和形式参数的匹配情况确定具体器根据实际参数和形式参数的匹配情况确定具体调用的是那个函数,将这个函数的内部函数名取调用的是那个函数,将这个函数的内部函数名取代重载的函数
29、名。代重载的函数名。程序设计 cs.sjtu 2011.9程序设计-40第第6章章 过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2011.9程序设计-41函数模板函数模板v如果一组重载函数仅仅是参数的类型不一样,程如果一组重载函数仅仅是参数的类型不一样,程序的逻辑完全一样,那么这一组重载函数可以写序的逻辑完全一样,那么这
30、一组重载函数可以写成一个函数模板。成一个函数模板。v所谓的函数模板就是实现类型的参数化(泛型化)所谓的函数模板就是实现类型的参数化(泛型化),即把函数中某些形式参数的类型定义成参数,即把函数中某些形式参数的类型定义成参数,称为模板参数称为模板参数v在函数调用时,编译器根据实际参数的类型确定在函数调用时,编译器根据实际参数的类型确定模板参数的值,生成不同的模板函数。模板参数的值,生成不同的模板函数。程序设计 cs.sjtu 2011.9程序设计-42函数模板的定义函数模板的定义v一一般的定义形式般的定义形式template返回类型返回类型FunctionName(形式参数表形式参数表)/函数定义
31、体函数定义体v模板形式参数表可以包含基本数据类型,也可以包模板形式参数表可以包含基本数据类型,也可以包含类类型(需加前缀含类类型(需加前缀class)templateTmax(Ta,Tb)returnab?a:b;程序设计 cs.sjtu 2011.9程序设计-43函数模板的使用函数模板的使用vmaxNum=max(3,7);maxNum=max(3,7);vmaxChar=max(maxChar=max(z z,a a););vmaxDouble=max(3.5,4.6);maxDouble=max(3.5,4.6);v函数模板的实例化:函数模板的实例化:根据实际参数确定模板参数的值根据实际
32、参数确定模板参数的值将模板参数的值代入函数模板,形成一个真正将模板参数的值代入函数模板,形成一个真正的函数的函数程序设计 cs.sjtu 2011.9程序设计-44第第6章章 过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2011.9程序设计-45标识符的作用域标识符的作用域v一个标识符能被存取一个标识符能被存取的程序部分
33、,称为的程序部分,称为标识符的作用域标识符的作用域v标识符的作用域与程标识符的作用域与程序块有关。所谓的序块有关。所谓的程序块是带有声明程序块是带有声明的复合语句的复合语句v如右框中有两块如右框中有两块Int main(void)int a=2,b=3;cout a b;int a=4;cout a b;cout a b;程序设计 cs.sjtu 2011.9程序设计-46标识符的作用域标识符的作用域续续v在块中说明的标识符是在块中说明的标识符是局部局部的,仅能在本块中的,仅能在本块中和内部的块中存取。和内部的块中存取。v当内部块与外部块有同名标识符时,在内部块当内部块与外部块有同名标识符时,
34、在内部块中屏蔽外部块的同名标识符。中屏蔽外部块的同名标识符。v在一个函数中,我们不能存取主调程序的变量,在一个函数中,我们不能存取主调程序的变量,即使知道该变量的名字。即使知道该变量的名字。v函数参数对该函数也是局部的,可以将它看成函数参数对该函数也是局部的,可以将它看成在块内,即函数体内说明的说明的变量。在块内,即函数体内说明的说明的变量。程序设计 cs.sjtu 2011.9程序设计-47局部变量和全局变量局部变量和全局变量v局部变量:在块内定义的变量称为局部变量,局部变量:在块内定义的变量称为局部变量,即使是即使是main函数中定义的变量也是局部的。函数中定义的变量也是局部的。v全局变量
35、:在所有的函数外面定义的变量称为全局变量:在所有的函数外面定义的变量称为全局变量全局变量作用范围:从定义位置到文件结束。如在作用范围作用范围:从定义位置到文件结束。如在作用范围外的函数要使用此变量,用关键词外的函数要使用此变量,用关键词extern在函数内说在函数内说明此全局变量。明此全局变量。作用:方便函数间的数据传递作用:方便函数间的数据传递v请写出下列程序的执行结果:请写出下列程序的执行结果:程序设计 cs.sjtu 2011.9程序设计-48intp=1,q=5,r=3;intf1()intp=3,r=2;q=p+q+r;cout“f1:p,q,r=“pqr;intf2()p=p+q+
36、r;cout“f2:p,q,r=“p q r p q r;intf3()intq;r=2*r;q=r+p;cout“f3:p,q,r=“pqr;main()f3();cout“afterf3:p,q,r=”p q r p q r;f1();cout“afterf1:p,q,r=“pqr;f2();cout“afterf2:p,q,r=”p q r p q r;结果:结果:f3:p,q,r=176afterf3:p,q,r=156f1:p,q,r=3102afterf1:p,q,r=1106f2:p,q,r=17106afterf2:p,q,r=17106程序设计 cs.sjtu 2011.9程
37、序设计-49全局变量的使用说明全局变量的使用说明v全局变量破坏了模块化,建议尽量少使全局变量破坏了模块化,建议尽量少使用用v当全局变量和局部变量同名时,在局部当全局变量和局部变量同名时,在局部变量的作用范围中全局变量被屏蔽。变量的作用范围中全局变量被屏蔽。v全局变量的使用将在模块化设计中详细全局变量的使用将在模块化设计中详细介绍介绍程序设计 cs.sjtu 2011.9程序设计-50第第6章章 过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函数内联函数v重载函数重载函数v函数模版函数模版v变量的作
38、用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2011.9程序设计-51存储类型存储类型v在在C+语言中,每个变量有两个属性:语言中,每个变量有两个属性:类型:变量所存储的数据类型类型:变量所存储的数据类型存储类型:变量所存储的区域:存储类型:变量所存储的区域:v标准的变量定义:标准的变量定义:存储类型存储类型数据类型数据类型变量名;变量名;v存储类型:存储类型:自动变量:自动变量:auto寄存器变量:寄存器变量:register外部变量:外部变量:extern静态变量:静态变量:static程序设计 cs.sjtu 2
39、011.9程序设计-52autov在函数内或块内定义的变量缺省时是在函数内或块内定义的变量缺省时是auto。如。如autointi;v当进入块时,系统为自动变量分配空间。当进入块时,系统为自动变量分配空间。当退出块时,系统释放分配给自动变量当退出块时,系统释放分配给自动变量的值。因此自动变量的值就消失了。当的值。因此自动变量的值就消失了。当再次进入该块时,系统重新分配空间。再次进入该块时,系统重新分配空间。程序设计 cs.sjtu 2011.9程序设计-53registerv存储在寄存器中,代替自动变量或形参,存储在寄存器中,代替自动变量或形参,可以提高变量的访问速度。可以提高变量的访问速度。
40、v如无合适的寄存器可用,则编译器把它如无合适的寄存器可用,则编译器把它设为自动变量。设为自动变量。程序设计 cs.sjtu 2011.9程序设计-54externv声明一个不在本模块作用范围内的全局变量。如:声明一个不在本模块作用范围内的全局变量。如:externintnum;num为一个的全局变量。为一个的全局变量。v用途:用途:在某函数中引用了一个声明在本函数后的全局变量时,在某函数中引用了一个声明在本函数后的全局变量时,需要在函数内用需要在函数内用extern声明此全局变量。声明此全局变量。当一个程序有多个源文件组成时,用当一个程序有多个源文件组成时,用extern可引用另一可引用另一文
41、件中的全局变量。文件中的全局变量。程序设计 cs.sjtu 2011.9程序设计-55/file1.cpp#include using namespace std;void f();extern int x;/外部变量的声明外部变量的声明int main()f();cout in main():x=“x endl;return 0;/file2.cpp#include using namespace std;int x;/全局变量的定义全局变量的定义void f()cout in f():x=“x endl;程序设计 cs.sjtu 2011.9程序设计-56staticv为在整个程序的运行期
42、间都存在的变量为在整个程序的运行期间都存在的变量限定访问范围。限定访问范围。v两类静态变量:两类静态变量:静态的局部变量静态的局部变量静态的外部变量静态的外部变量程序设计 cs.sjtu 2011.9程序设计-57静态的局部变量静态的局部变量v允许局部允许局部变量保存变量保存它的原有它的原有值,以便值,以便在次进入在次进入块时还可块时还可以使用此以使用此值。值。eg.intf(inta)intb=0;staticintc=3;b=b+1;c=c+1;return(a+b+c);voidmain()inta=2,i;for(i=0;i3;+i)coutf(a);运行结果为:运行结果为:789程序
43、设计 cs.sjtu 2011.9程序设计-58静态的外部变量静态的外部变量v用用static说明的全局变量其他源文件不能说明的全局变量其他源文件不能用用extern引用它引用它v用用extern还可以用在函数定义或说明中。还可以用在函数定义或说明中。该函数只能被用于本源文件中,其他源该函数只能被用于本源文件中,其他源文件不能调用此函数。文件不能调用此函数。程序设计 cs.sjtu 2011.9程序设计-59静态变量的使用静态变量的使用v未被程序员初始化的静态变量都由系统初未被程序员初始化的静态变量都由系统初始化为始化为0。v局部静态变量的初值是编译时赋的。当运局部静态变量的初值是编译时赋的。
44、当运行时重复调用此函数时,不重复赋初值。行时重复调用此函数时,不重复赋初值。v虽然局部静态变量在函数调用结束后仍然虽然局部静态变量在函数调用结束后仍然存在,但其他函数不能引用它。存在,但其他函数不能引用它。程序设计 cs.sjtu 2011.9程序设计-60voida();voidb();voidc();voidd();main()intx=6;cout“xinmainis“xendl;a();b();c();d(x);x+;a();b();c();d(x);cout“xinmainis”xendl;voida()intx=25;cout“xinais”xendl;voidb()statici
45、ntx=50;cout“xinbis”x+endl;voidc()externintx;x*=10;cout“xincis”xendl;intx=2;voidd(intx)cout“xindis”+xendl;结果:结果:xinmainis6xinais25xinbis50 xincis20 xindis7xinais25xinbis51xinc200 xindis8xinmainis7程序设计 cs.sjtu 2011.9程序设计-61第第6章章 过程封装函数过程封装函数v函数函数v自己编写函数自己编写函数v函数的使用函数的使用v数组作为参数数组作为参数v带默认值的函数带默认值的函数v内联函
46、数内联函数v重载函数重载函数v函数模版函数模版v变量的作用域变量的作用域v变量的存储类别变量的存储类别v递归函数递归函数v基于递归的算法基于递归的算法程序设计 cs.sjtu 2011.9程序设计-62递归用途递归用途v递归程序设计:将一个大问题简化为递归程序设计:将一个大问题简化为同样形同样形式式的较小问题。的较小问题。在一个递归求解中,分解的子问题与最初的问题在一个递归求解中,分解的子问题与最初的问题具有一样的形式具有一样的形式 作为处理问题的工具,递归技术是一种非常有力作为处理问题的工具,递归技术是一种非常有力的工具。利用递归不但可以使得书写复杂度降低,的工具。利用递归不但可以使得书写复
47、杂度降低,而且使程序看上去更加美观而且使程序看上去更加美观v递归调用:在一个函数中直接或间接地调用递归调用:在一个函数中直接或间接地调用函数本身函数本身程序设计 cs.sjtu 2011.9程序设计-63递归条件递归条件v必须有递归终止的条件必须有递归终止的条件 v函数有与递归终止条件相关的参数函数有与递归终止条件相关的参数v在递归过程中,决定终止条件的参数有在递归过程中,决定终止条件的参数有规略地递增或递减规略地递增或递减 程序设计 cs.sjtu 2011.9程序设计-64递归的递归的标准模式标准模式v有可对函数的入口进行有可对函数的入口进行测试的基本情况测试的基本情况if(条件条件)re
48、turn(不需要递归的简单答案不需要递归的简单答案);elsereturn(递归调用同一函数递归调用同一函数);基本情况基本情况程序设计 cs.sjtu 2011.9程序设计-65典型的递归函数典型的递归函数阶乘函数阶乘函数n!=1*2*3*4*(n1)*n(n1)!递归形式:递归形式:递归终止条件递归终止条件longp(intn)if(n=0)return1;elsereturnn*p(n1);程序设计 cs.sjtu 2011.9程序设计-66简单应用简单应用求求n的的k次幂次幂intRaiseIntToPower(intn,intk)if(k=0)return(1);elsereturn
49、(n*RaiseIntToPower(n,k1);程序设计 cs.sjtu 2011.9程序设计-67Fibonacci函数函数00112132435568intf(intn)if(n=0)return0;elseif(n=1)return1;elsereturn(f(n1)+f(n2);程序设计 cs.sjtu 2011.9程序设计-68理解递归理解递归v问题:求解问题:求解n!可可以以用用循循环环的的方方法法,即即从从1开开始始,乘乘2,再再乘乘3.一一直直乘乘到到n。这这种种方方法法容容易易理理解解,也容易实现也容易实现由由于于n!=n(n-1)!(n-1)!数数学学里里定定义义0!1,
50、从从而而n!可以用下面的递归公式表示:可以用下面的递归公式表示:程序设计 cs.sjtu 2011.9程序设计-69递归函数设计递归函数设计intp(intn)if(n=0)return(1);elsereturn(n*p(n1);程序设计 cs.sjtu 2011.9程序设计-70递归执行的过程递归执行的过程求求p(4)递归过程回溯程序设计 cs.sjtu 2011.9程序设计-71递归与迭代的选择递归与迭代的选择v对于大多数常用的递归都有简单、等价对于大多数常用的递归都有简单、等价的迭代程序。究竟使用哪一种,凭你的的迭代程序。究竟使用哪一种,凭你的经验选择。经验选择。v迭代程序复杂,但效率