C-程序设计-第5章函数与预处理课件_第1页
C-程序设计-第5章函数与预处理课件_第2页
C-程序设计-第5章函数与预处理课件_第3页
C-程序设计-第5章函数与预处理课件_第4页
C-程序设计-第5章函数与预处理课件_第5页
已阅读5页,还剩89页未读 继续免费阅读

下载本文档

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

文档简介

第五章函数与预处理函数的定义函数的调用指针与函数函数的嵌套调用函数的递归调用局部变量和全局变量变量的存储类型11/21/20221函数与预处理第五章函数与预处理函数的定义11/21/20221函数与预§5.1.1函数的引入#include<iostream.h>voidmain(){intn=30;for(inti=0;i<n;i++)cout<<'-';cout<<endl;cout<<"方法的引入"<<endl;for(i=0;i<n;i++)cout<<'-';cout<<endl;}【运行结果】

------------------------------方法的引入------------------------------一段程序被执行了多次优化程序结构通用:函数库11/21/20222函数与预处理§5.1.1函数的引入#include<iostrea#include<iostream.h>voidmain(){intn=30;dline(n);cout<<"方法的引入"<<endl;

dline(n);}voiddline(intm){for(inti=0;i<m;i++)cout<<'-';cout<<endl;}主调函数被调函数11/21/20223函数与预处理#include<iostream.h>voiddlin§5.1函数定义函数体例:intadd(intx,inty){returnx+y;}数据类型函数名(形参列表){ 语句序列

}函数说明voidmain(){inta,b,s;cin>>a>>b;s=add(a,b);cout<<s<<endl;}testMethod.cpp11/21/20224函数与预处理§5.1函数定义函数体例:数据类型函数名(形参列表)函⑴返回值类型规定了方法返回值的类型。返回值由return提供。注意:若方法无返回值,数据类型应为void。⑵方法名是有效的c++标识符。⑶形参表是用逗号隔开的变量说明列表。注意:函数可以无参数。可将函数分为两类:无参方法与有参方法。注:函数说明后无分号intadd(intx,inty){returnx+y;}返回值类型方法名(形参表)voidmyprint(){System.out.print("***");}doublearea(doublex,y,z){ }清楚了吗?11/21/20225函数与预处理⑴返回值类型规定了方法返回值的类型。返回值由return提供5.1.3return语句语句格式: return; //无值void return表达式;//有值 return(表达式);//有值函数体中的流程控制语句。先计算表达式的值,然后从被调方法返回到主调方法,表达式的值作为函数的返回值。(注意:只能返回一个值)函数值的类型:以函数定义的类型为准,若不同,需将return语句表达式的值转换类型。无返回值void时,可无return语句,执行到函数体}时返回。11/21/20226函数与预处理5.1.3return语句语句格式:11/21/202265.1.4函数声明(函数原型)函数原型的形式:

数据类型函数名(形参类型说明);

例:doublearea(double,double,double);C++要求在调用函数前让编译器知道其函数原型,以便编译器利用函数原型提供的信息来检查调用的合法性,强制参数为适当类型,保证参数的正确传递。而编译器获得函数原型有两种情况:(1)当函数定义在调用之前时,则从定义中抽取函数原型。(2)当函数定义在调用之后时,则程序员须在调用之前用函数原型对函数进行声明,让编译器获得函数原型。11/21/20227函数与预处理5.1.4函数声明(函数原型)函数原型的形式:

数据类型对于标准库函数的函数原型都在头文件中提供了,程序可用#include命令包含进来即可;注意:函数原型和函数定义在返回类型、函数名和参数表上必须完全一致,否则编译错误。注意11/21/20228函数与预处理对于标准库函数的函数原型都在头文件中提供了,程序可用#inc一、函数调用形式:函数名(实参列表)§5.2函数的调用 t=sqrt(t*(t-a)*(t-b)*(t-c));s=area(a,b,c);s=sum(5,7

);例11/21/20229函数与预处理一、函数调用形式:函数名(实参列表)§5.2函数的调用 tmain(){……s=area(a,b,c);……}函数调用1.实参的个数、类型、顺序要与形参对应一致2.函数间相互独立:各函数中的变量互不相关,可同名。3.可以没有参数,但圆括号一定要有,不能省略主方法被调方法floatarea(intx,inty,intz){……returns……}实参形参

参数传递?

返回值11/21/202210函数与预处理main()函数调用1.实参的个数、类型、顺序要与形参对应函数的传值调用C++中变量值有两种:变量本身值和变量地址值。而形参的类型也就分为两种:一般类型和指针类型。则传值调用的方式也有两种:传值调用和传址调用有时也称:直接调用与间接调用1、传值调用的实现机制和特点实现机制是:调用函数中的数据只是在调用之初通过实参向形参传递,之后各占有不同的空间,并且不再发生联系,互不干扰。特点是:形参值的改变不影响实参。transferValue.cpptestTransefer.cpp11/21/202211函数与预处理函数的传值调用C++中变量值有两种:变量本身值和变量地址值。内存解析a:3b:5a:3b:5temp:35311/21/202212函数与预处理内存解析a:3b:5a:3b:5temp:35311/2实现机制是:实参为某变量地址值,形参为指针类型。在调用时,将地址值赋给形参,使形参指针指向该变量。则以后可直接通过形参指针来访问该变量。特点是:可通过改变形参所指向的变量值来影响实参所对应的变量值。2、传址调用的实现机制和特点transferAddress.cpp11/21/202213函数与预处理实现机制是:实参为某变量地址值,形参为指针类型。在调用时,将内存解析a:3b:5a:&ab:&btemp:35311/21/202214函数与预处理内存解析a:3b:5a:&ab:&btemp:35311函数的引用调用使用引用作为函数形参时,调用函数的实参要用变量名。将实参变量名赋给形参的引用,则在被调函数中,对引用的操作,实质就是直接通过引用来操作实参的变量值。显然,引用传递方式具有传址调用的效果,又有传值调用的语法简单性和可读性。注意:若只从调用语句观察,是无法区别采用的是传值调用还是引用调用。transReference.cpp11/21/202215函数与预处理函数的引用调用使用引用作为函数形参时,调用函数的实参要用变量内存解析a:3b:5mntemp:35311/21/202216函数与预处理内存解析a:3b:5mntemp:35311/21/2022使用数组作函数参数1、形参和实参都用数组这种调用的机制是:形参和实参共用内存中的同一个数组空间。2、形参用对应数组的指针实际,也可一个使用指针,另一个使用数组。li5_17.cppvoidconvert(char*s)voidconvert(chars[])两种定义等价convert(t)testTransArray.cpp11/21/202217函数与预处理使用数组作函数参数1、形参和实参都用数组li5_17.cpp内存解析…\0GdAt:&t[0]s:&t[0]#include<iostream.h>voidconvert(char*);voidmain(){ chart[10]="AdG"; convert(t); cout<<t<<endl;}voidconvert(char*s){*s='B';s[1]='C';}11/21/202218函数与预处理内存解析…\0GdAt:&t[0]s:&t[0]#incl3、形参用引用实参用数组名…\0GdAt:&t[0]s#include<iostream.h>typedefchararray[10];voidconvert(array&s);voidmain(){chart[10]="AdG"; convert(t); cout<<t<<endl;}voidconvert(array&s){s[0]='B';}11/21/202219函数与预处理3、形参用引用实参用数组名…\0GdAt:&t[0]s#in作业一、课后作业复习教材第五章:5-1、5-2、5-3-1、5-3-2二、上机作业实验九:范例9.1,9.3,2.编程题:(2)实验十:范例10.1,10.6;2.编程(4)三、预习:第五章5.4~5.9节11/21/202220函数与预处理作业一、课后作业11/21/202220函数与预处理§5-4函数的嵌套调用 main(){……调用a函数...}a函数{…调用b函数…}b函数{………}①③④⑤⑥⑦②在被调函数中,又调用了函数----嵌套调用11/21/202221函数与预处理§5-4函数的嵌套调用 main()a函数b函数①③④⑤#include<iostream.h>doublearea(double,double,double);voidmain(){doublea,b,c,s;cout<<"inputa,b,c=";cin>>a>>b>>c;s=area(a,b,c);cout<<“area=“<<s<<“\n”;}#include<math.h>doublearea(doublex,doubley,doublez){doubles;if(x+y<z||x+z<y||y+z<x)return0;s=(x+y+z)/2;s=sqrt(s*(s-x)*(s-y)*(s-z));returns;}doublesqrt(…){………return…}求三角形面积testArea.cpp11/21/202222函数与预处理#include<iostream.h>#include<§5-5函数的递归调用函数的递归调用是指,一个函数在它的函数体内,直接或间接地调用它自身。如:求n!的程序

longfac(intn){if(n>1)returnfac(n-1)*n;elsereturn1;}

注意两个递归条件:(1)初始条件:n=1时,n!=1(2)递归公式:n>1时,n!=n*(n-1)!

n!=n=1n*(n-1)!n>1testRecursionFuncion.cpp11/21/202223函数与预处理§5-5函数的递归调用函数的递归调用是指,一个函数在它的函………

………

fac(10)10*fac(9)9*fac(8)3*fac(2)fac(1)=1………2*1=2………9*40320=3628802*fac(1)3*2=610*362880=3628800递推过程回归过程递归终止条件11/21/202224函数与预处理………………fac(10)10*fac(9)9*fa5.6.1

内联函数引入原因目的是为了解决程序中函数调用的效率问题。函数调用时需要建立栈内存环境,进行参数传递,并产生程序执行转移,则都要有时间和空间的代价。而有时一些函数代码很短(1~5行),却有高使用频率,造成处理现场的开销巨增。这时若将函数体嵌入函数调用处,则可避免每次调用函数的开销。大大提高效率。11/21/202225函数与预处理5.6.1内联函数引入原因目的是为了解决程序中函数调用的效C++通过将该函数声明为inline来实现。即在函数声明和定义中用inline来修饰。如:inlineintisnumber(charc){return(ch>='0'&&ch<='9')?1:0;}voidmain(){charch;for(intI=1;I<=10;I++){cin>>ch;intp=isnumber(ch);cout<<p<<endl;}}编译器在看到inline后,为该函数创建一段代码,以便以后每次碰到该函数的调用都用相应代码来替代。定义方法11/21/202226函数与预处理C++通过将该函数声明为inline来实现。定义方法11/2注意事项内联函数可以在一开始仅声明一次,但必须在被调用之前声明或定义为inline。因为内联函数的代码必须在被替换前生成被替换的代码。否则编译器同一般函数对待,产生函数调用。内联函数还有限制:函数内不能含有循环结构或switch结构;不能是递归函数。内联函数的定义必须出现在内联函数第一次被调用之前注意11/21/202227函数与预处理注意事项内联函数可以在一开始仅声明一次,但必须在被调用之前声*5.6.2函数重载(自学)引入原因重载指用同一个函数名对应着多个函数实现的情况。如:求两个数的较大值,若数的类型不同,则返回值类型不同。

intmax(int,int);…floatc=max(3.14,3.5);//error因此一个定义了实现整型数比较功能的函数无法用于实现实型数的比较,尽管其功能一致。这时就可采用重载。11/21/202228函数与预处理*5.6.2函数重载(自学)引入原因重载指用同一个函数名对在C++中,允许两个或两个以上的函数采用相同的名字,只要使用不同类型、不同数目的参数,编译器便知道在什么情况下该调用哪个函数,这就叫函数重载。如:intmax(intx,inty){return((x>y)?x:y);}

doublemax(doublex,doubley){return((x>y)

?x:y);}#include<iostream.h>voidmain(){cout<<max(10,20)<<endl;cout<<max(1.23,2.34)<<endl;}重载方式11/21/202229函数与预处理在C++中,允许两个或两个以上的函数采用相同的名字,只要使用(1)作为重载函数至少在参数个数、参数类型上有所不同。若仅在返回类型上不同,编译器是无法区别的。如:voidfunc(int);intfunc(int);//错误

intmin(int,int);intmin(int,int,int);//正确

intadd(int,int);doubleadd(double,double);//正确(2)typedef定义的类型只是给已有类型取另外一个名字,编译器不能将其同原类型区分。如:

typedefINTint;voidfunc(intx){...}voidfunc(INTx){…}(3)重载函数一般应具有相同的功能,否则会破坏程序的可读性。注意事项11/21/202230函数与预处理(1)作为重载函数至少在参数个数、参数类型上有所不同。若仅在*函数参数的求值顺序(自学)由于使用不同求值顺序的编译器而造成二义性。#include<iostream.h>intadd(intx,inty);//函数声明voidmain(){inta=4,b=6;intz=add(++a,a+b);//从左至右为511cout<<z<<endl;//从右至左为510}intadd(intx,inty)//函数定义(实现){returnx+y;}注:改变函数的实参的写法,尽量避免二义性的出现。11/21/202231函数与预处理*函数参数的求值顺序(自学)由于使用不同求值顺序的编译器而造*设置函数参数的默认值(自学)在函数说明语句中预先初始化一些参数的值,从而使调用语句中相应的参数可以缺省。如:

intmax(int,int,int=-32768);则在函数调用时可以不给最后一个参数传递值,而采用缺省值。如:

max(i1,i2);//参数缺省调用

max(i1,i2,i3);//正常调用允许函数默认参数值,是为了让编程简单。设置函数参数的默认值是按从右至左的方式当又有声明又有定义时,定义中不允许默认参数。若只有定义,则默认参数才可出现在函数定义中。11/21/202232函数与预处理*设置函数参数的默认值(自学)在函数说明语句中预先初始化一些注意:若一个函数中有多个默认参数,则参数缺省按从后向前的顺序进行,如:voidfun(inta=3,int,charc='a');//error

当调用函数时,也只能从右向左匹配参数。如:声明函数为:voidfunc(inta,intb=2,intc=3,intd=5);则调用方法:func(2,15,,3);//error11/21/202233函数与预处理注意:若一个函数中有多个默认参数,则参数缺省按从后向前的顺序5-8作用域与生命期p162作用域一个变量在一个程序运行中能被使用的范围,在此作用域中可以引用该变量。

生命期

一个变量在一个程序运行中存在的期间,称为该变量的“生存期”。11/21/202234函数与预处理5-8作用域与生命期p162作用域生命期

一个变量在一个标识符的作用域(scope)规则规则为:标识符只能在说明它或定义它的范围内是可见的,而在该范围之外是不可见的。不同的标识符定义在不同的范围内有不同的作用域。按作用域的大小可分为:

程序级:包含着组成该程序的所有文件。

文件级:仅在定义它的文件内。

函数级:在它所定义的函数体内。

块级(语句):定义在分程序中、语句块内。11/21/202235函数与预处理标识符的作用域(scope)规则规则为:不同的标识符定义在不#include<iostream.h>inta=1;voidmain(){

intx=3;//doublex(3.5);error inty(5);

if(x>2) {

intx(4); cout<<x<<"\t"<<y<<"\t"; } cout<<endl<<x<<"\t"<<y<<endl;}testScope.cpp11/21/202236函数与预处理#include<iostream.h>testScope1、局部变量是指作用域在函数级和块级的变量。2、全局变量是指作用域在程序级和文件级的变量。5-8-2局部变量和全局变量11/21/202237函数与预处理1、局部变量5-8-2局部变量和全局变量11/21/202#include<iostream.h>intx=1,y=2,z=3;fun1

(int

x){int

z;

z

=x+y;

y=1;cout<<“x=“<<x<<“y=“<<y<<“z=“<<z;returnz;}voidmain(){int

a=10;

x=fun1(a);cout<<"x=“<<x<<“y=“<<y<<“z=“<<z<<“\n”;}全局变量局部变量输出结果:

x=10,y=1,z=12局部变量与全局变量同名x=12,y=1,z=311/21/202238函数与预处理#include<iostream.h>全局变量局部变量输出5-8-3生命期一、局部变量的存储类别二、全局变量的存储类别11/21/202239函数与预处理5-8-3生命期一、局部变量的存储类别二、全局变量的存储类别程序load到内存区硬盘heapsegstacksegdatasegcodeseg执行过程内存管理new...局部变量全局变量静态变量字符串常量内存找到main()开始执行符号表11/21/202240函数与预处理程序load到内存区硬盘heapsegstacksegd一、局部变量的存储类别自动变量auto:局部变量的缺省存储类型。静态局部变量static静态变量只初始化一次,在编译时进行。寄存器变量registerautointc;intc;staticinti;registerintj;等价11/21/202241函数与预处理一、局部变量的存储类别自动变量auto:局部变量的缺省存局部变量的自动和静态存储类型举例#include<iostream.h>fun1(intx){staticinty=1;intz=10;x=x+y;y=x+z;cout<<x<<ycout<<z<<endl;}voidmain(){fun1(1);fun1(1);} y:z:10x:2112z:10x:132311/21/202242函数与预处理局部变量的自动和静态存储类型举例#include<iost2、全局变量的存储类别静态外部变量static

静态外部变量作用域为本程序文件,其它程序文件不能使用外部变量extern外部变量除本程序文件使用外,也可被其它程序文件使用全局变量的声明:在定义外部变量之前使用该变量,需对其声明extern数据类型变量名表;注意:用extern声明只是起一个说明作用,不产生新变量,与定义变量不同11/21/202243函数与预处理2、全局变量的存储类别静态外部变量static

静态外部//文件file1.cpp#include<iostream.h>inta=2;//全局变量intadd(intn);//原型说明voidmain(){intb=3,c,d;c=a*b;cout<<a<<b<<c<<endl;d=add(b);cout<<a<<b<<d;}//文件file2.cppexterninta;intadd(intn){returnn+a;}求a×b和a+b的值a:2b:3c:6n:3d:511/21/202244函数与预处理//文件file1.cpp//文件file2.cpp求a*5.9编译预处理(自学)文件包含命令条件编译命令宏定义命令11/21/202245函数与预处理*5.9编译预处理(自学)文件包含命令11/21/2022作业一、课后作业复习教材第五章:5-1、5-2、5-3-1、5-3-2二、上机作业实验九:范例9.1,9.3,2.编程题:(2)实验十:范例10.1,10.6;2.编程(4)三、预习:第五章5.4~5.9节11/21/202246函数与预处理作业一、课后作业11/21/202246函数与预处理第十讲作业一、课后作业复习教材第五章二、上机作业实验十一:范例1~3;2.编程(3)实验十二:范例1、3、4;三、预习:第六章11/21/202247函数与预处理第十讲作业一、课后作业11/21/202247函数与预处理第五章函数与预处理函数的定义函数的调用指针与函数函数的嵌套调用函数的递归调用局部变量和全局变量变量的存储类型11/21/202248函数与预处理第五章函数与预处理函数的定义11/21/20221函数与预§5.1.1函数的引入#include<iostream.h>voidmain(){intn=30;for(inti=0;i<n;i++)cout<<'-';cout<<endl;cout<<"方法的引入"<<endl;for(i=0;i<n;i++)cout<<'-';cout<<endl;}【运行结果】

------------------------------方法的引入------------------------------一段程序被执行了多次优化程序结构通用:函数库11/21/202249函数与预处理§5.1.1函数的引入#include<iostrea#include<iostream.h>voidmain(){intn=30;dline(n);cout<<"方法的引入"<<endl;

dline(n);}voiddline(intm){for(inti=0;i<m;i++)cout<<'-';cout<<endl;}主调函数被调函数11/21/202250函数与预处理#include<iostream.h>voiddlin§5.1函数定义函数体例:intadd(intx,inty){returnx+y;}数据类型函数名(形参列表){ 语句序列

}函数说明voidmain(){inta,b,s;cin>>a>>b;s=add(a,b);cout<<s<<endl;}testMethod.cpp11/21/202251函数与预处理§5.1函数定义函数体例:数据类型函数名(形参列表)函⑴返回值类型规定了方法返回值的类型。返回值由return提供。注意:若方法无返回值,数据类型应为void。⑵方法名是有效的c++标识符。⑶形参表是用逗号隔开的变量说明列表。注意:函数可以无参数。可将函数分为两类:无参方法与有参方法。注:函数说明后无分号intadd(intx,inty){returnx+y;}返回值类型方法名(形参表)voidmyprint(){System.out.print("***");}doublearea(doublex,y,z){ }清楚了吗?11/21/202252函数与预处理⑴返回值类型规定了方法返回值的类型。返回值由return提供5.1.3return语句语句格式: return; //无值void return表达式;//有值 return(表达式);//有值函数体中的流程控制语句。先计算表达式的值,然后从被调方法返回到主调方法,表达式的值作为函数的返回值。(注意:只能返回一个值)函数值的类型:以函数定义的类型为准,若不同,需将return语句表达式的值转换类型。无返回值void时,可无return语句,执行到函数体}时返回。11/21/202253函数与预处理5.1.3return语句语句格式:11/21/202265.1.4函数声明(函数原型)函数原型的形式:

数据类型函数名(形参类型说明);

例:doublearea(double,double,double);C++要求在调用函数前让编译器知道其函数原型,以便编译器利用函数原型提供的信息来检查调用的合法性,强制参数为适当类型,保证参数的正确传递。而编译器获得函数原型有两种情况:(1)当函数定义在调用之前时,则从定义中抽取函数原型。(2)当函数定义在调用之后时,则程序员须在调用之前用函数原型对函数进行声明,让编译器获得函数原型。11/21/202254函数与预处理5.1.4函数声明(函数原型)函数原型的形式:

数据类型对于标准库函数的函数原型都在头文件中提供了,程序可用#include命令包含进来即可;注意:函数原型和函数定义在返回类型、函数名和参数表上必须完全一致,否则编译错误。注意11/21/202255函数与预处理对于标准库函数的函数原型都在头文件中提供了,程序可用#inc一、函数调用形式:函数名(实参列表)§5.2函数的调用 t=sqrt(t*(t-a)*(t-b)*(t-c));s=area(a,b,c);s=sum(5,7

);例11/21/202256函数与预处理一、函数调用形式:函数名(实参列表)§5.2函数的调用 tmain(){……s=area(a,b,c);……}函数调用1.实参的个数、类型、顺序要与形参对应一致2.函数间相互独立:各函数中的变量互不相关,可同名。3.可以没有参数,但圆括号一定要有,不能省略主方法被调方法floatarea(intx,inty,intz){……returns……}实参形参

参数传递?

返回值11/21/202257函数与预处理main()函数调用1.实参的个数、类型、顺序要与形参对应函数的传值调用C++中变量值有两种:变量本身值和变量地址值。而形参的类型也就分为两种:一般类型和指针类型。则传值调用的方式也有两种:传值调用和传址调用有时也称:直接调用与间接调用1、传值调用的实现机制和特点实现机制是:调用函数中的数据只是在调用之初通过实参向形参传递,之后各占有不同的空间,并且不再发生联系,互不干扰。特点是:形参值的改变不影响实参。transferValue.cpptestTransefer.cpp11/21/202258函数与预处理函数的传值调用C++中变量值有两种:变量本身值和变量地址值。内存解析a:3b:5a:3b:5temp:35311/21/202259函数与预处理内存解析a:3b:5a:3b:5temp:35311/2实现机制是:实参为某变量地址值,形参为指针类型。在调用时,将地址值赋给形参,使形参指针指向该变量。则以后可直接通过形参指针来访问该变量。特点是:可通过改变形参所指向的变量值来影响实参所对应的变量值。2、传址调用的实现机制和特点transferAddress.cpp11/21/202260函数与预处理实现机制是:实参为某变量地址值,形参为指针类型。在调用时,将内存解析a:3b:5a:&ab:&btemp:35311/21/202261函数与预处理内存解析a:3b:5a:&ab:&btemp:35311函数的引用调用使用引用作为函数形参时,调用函数的实参要用变量名。将实参变量名赋给形参的引用,则在被调函数中,对引用的操作,实质就是直接通过引用来操作实参的变量值。显然,引用传递方式具有传址调用的效果,又有传值调用的语法简单性和可读性。注意:若只从调用语句观察,是无法区别采用的是传值调用还是引用调用。transReference.cpp11/21/202262函数与预处理函数的引用调用使用引用作为函数形参时,调用函数的实参要用变量内存解析a:3b:5mntemp:35311/21/202263函数与预处理内存解析a:3b:5mntemp:35311/21/2022使用数组作函数参数1、形参和实参都用数组这种调用的机制是:形参和实参共用内存中的同一个数组空间。2、形参用对应数组的指针实际,也可一个使用指针,另一个使用数组。li5_17.cppvoidconvert(char*s)voidconvert(chars[])两种定义等价convert(t)testTransArray.cpp11/21/202264函数与预处理使用数组作函数参数1、形参和实参都用数组li5_17.cpp内存解析…\0GdAt:&t[0]s:&t[0]#include<iostream.h>voidconvert(char*);voidmain(){ chart[10]="AdG"; convert(t); cout<<t<<endl;}voidconvert(char*s){*s='B';s[1]='C';}11/21/202265函数与预处理内存解析…\0GdAt:&t[0]s:&t[0]#incl3、形参用引用实参用数组名…\0GdAt:&t[0]s#include<iostream.h>typedefchararray[10];voidconvert(array&s);voidmain(){chart[10]="AdG"; convert(t); cout<<t<<endl;}voidconvert(array&s){s[0]='B';}11/21/202266函数与预处理3、形参用引用实参用数组名…\0GdAt:&t[0]s#in作业一、课后作业复习教材第五章:5-1、5-2、5-3-1、5-3-2二、上机作业实验九:范例9.1,9.3,2.编程题:(2)实验十:范例10.1,10.6;2.编程(4)三、预习:第五章5.4~5.9节11/21/202267函数与预处理作业一、课后作业11/21/202220函数与预处理§5-4函数的嵌套调用 main(){……调用a函数...}a函数{…调用b函数…}b函数{………}①③④⑤⑥⑦②在被调函数中,又调用了函数----嵌套调用11/21/202268函数与预处理§5-4函数的嵌套调用 main()a函数b函数①③④⑤#include<iostream.h>doublearea(double,double,double);voidmain(){doublea,b,c,s;cout<<"inputa,b,c=";cin>>a>>b>>c;s=area(a,b,c);cout<<“area=“<<s<<“\n”;}#include<math.h>doublearea(doublex,doubley,doublez){doubles;if(x+y<z||x+z<y||y+z<x)return0;s=(x+y+z)/2;s=sqrt(s*(s-x)*(s-y)*(s-z));returns;}doublesqrt(…){………return…}求三角形面积testArea.cpp11/21/202269函数与预处理#include<iostream.h>#include<§5-5函数的递归调用函数的递归调用是指,一个函数在它的函数体内,直接或间接地调用它自身。如:求n!的程序

longfac(intn){if(n>1)returnfac(n-1)*n;elsereturn1;}

注意两个递归条件:(1)初始条件:n=1时,n!=1(2)递归公式:n>1时,n!=n*(n-1)!

n!=n=1n*(n-1)!n>1testRecursionFuncion.cpp11/21/202270函数与预处理§5-5函数的递归调用函数的递归调用是指,一个函数在它的函………

………

fac(10)10*fac(9)9*fac(8)3*fac(2)fac(1)=1………2*1=2………9*40320=3628802*fac(1)3*2=610*362880=3628800递推过程回归过程递归终止条件11/21/202271函数与预处理………………fac(10)10*fac(9)9*fa5.6.1

内联函数引入原因目的是为了解决程序中函数调用的效率问题。函数调用时需要建立栈内存环境,进行参数传递,并产生程序执行转移,则都要有时间和空间的代价。而有时一些函数代码很短(1~5行),却有高使用频率,造成处理现场的开销巨增。这时若将函数体嵌入函数调用处,则可避免每次调用函数的开销。大大提高效率。11/21/202272函数与预处理5.6.1内联函数引入原因目的是为了解决程序中函数调用的效C++通过将该函数声明为inline来实现。即在函数声明和定义中用inline来修饰。如:inlineintisnumber(charc){return(ch>='0'&&ch<='9')?1:0;}voidmain(){charch;for(intI=1;I<=10;I++){cin>>ch;intp=isnumber(ch);cout<<p<<endl;}}编译器在看到inline后,为该函数创建一段代码,以便以后每次碰到该函数的调用都用相应代码来替代。定义方法11/21/202273函数与预处理C++通过将该函数声明为inline来实现。定义方法11/2注意事项内联函数可以在一开始仅声明一次,但必须在被调用之前声明或定义为inline。因为内联函数的代码必须在被替换前生成被替换的代码。否则编译器同一般函数对待,产生函数调用。内联函数还有限制:函数内不能含有循环结构或switch结构;不能是递归函数。内联函数的定义必须出现在内联函数第一次被调用之前注意11/21/202274函数与预处理注意事项内联函数可以在一开始仅声明一次,但必须在被调用之前声*5.6.2函数重载(自学)引入原因重载指用同一个函数名对应着多个函数实现的情况。如:求两个数的较大值,若数的类型不同,则返回值类型不同。

intmax(int,int);…floatc=max(3.14,3.5);//error因此一个定义了实现整型数比较功能的函数无法用于实现实型数的比较,尽管其功能一致。这时就可采用重载。11/21/202275函数与预处理*5.6.2函数重载(自学)引入原因重载指用同一个函数名对在C++中,允许两个或两个以上的函数采用相同的名字,只要使用不同类型、不同数目的参数,编译器便知道在什么情况下该调用哪个函数,这就叫函数重载。如:intmax(intx,inty){return((x>y)?x:y);}

doublemax(doublex,doubley){return((x>y)

?x:y);}#include<iostream.h>voidmain(){cout<<max(10,20)<<endl;cout<<max(1.23,2.34)<<endl;}重载方式11/21/202276函数与预处理在C++中,允许两个或两个以上的函数采用相同的名字,只要使用(1)作为重载函数至少在参数个数、参数类型上有所不同。若仅在返回类型上不同,编译器是无法区别的。如:voidfunc(int);intfunc(int);//错误

intmin(int,int);intmin(int,int,int);//正确

intadd(int,int);doubleadd(double,double);//正确(2)typedef定义的类型只是给已有类型取另外一个名字,编译器不能将其同原类型区分。如:

typedefINTint;voidfunc(intx){...}voidfunc(INTx){…}(3)重载函数一般应具有相同的功能,否则会破坏程序的可读性。注意事项11/21/202277函数与预处理(1)作为重载函数至少在参数个数、参数类型上有所不同。若仅在*函数参数的求值顺序(自学)由于使用不同求值顺序的编译器而造成二义性。#include<iostream.h>intadd(intx,inty);//函数声明voidmain(){inta=4,b=6;intz=add(++a,a+b);//从左至右为511cout<<z<<endl;//从右至左为510}intadd(intx,inty)//函数定义(实现){returnx+y;}注:改变函数的实参的写法,尽量避免二义性的出现。11/21/202278函数与预处理*函数参数的求值顺序(自学)由于使用不同求值顺序的编译器而造*设置函数参数的默认值(自学)在函数说明语句中预先初始化一些参数的值,从而使调用语句中相应的参数可以缺省。如:

intmax(int,int,int=-32768);则在函数调用时可以不给最后一个参数传递值,而采用缺省值。如:

max(i1,i2);//参数缺省调用

max(i1,i2,i3);//正常调用允许函数默认参数值,是为了让编程简单。设置函数参数的默认值是按从右至左的方式当又有声明又有定义时,定义中不允许默认参数。若只有定义,则默认参数才可出现在函数定义中。11/21/202279函数与预处理*设置函数参数的默认值(自学)在函数说明语句中预先初始化一些注意:若一个函数中有多个默认参数,则参数缺省按从后向前的顺序进行,如:voidfun(inta=3,int,charc='a');//error

当调用函数时,也只能从右向左匹配参数。如:声明函数为:voidfunc(inta,intb=2,intc=3,intd=5);则调用方法:func(2,15,,3);//error11/21/202280函数与预处理注意:若一个函数中有多个默认参数,则参数缺省按从后向前的顺序5-8作用域与生命期p162作用域一个变量在一个程序运行中能被使用的范围,在此作用域中可以引用该变量。

生命期

一个变量在一个程序运行中存在的期间,称为该变量的“生存期”。11/21/202281函数与预处理5-8作用域与生命期p162作用域生命期

一个变量在一个标识符的作用域(scope)规则规则为:标识符只能在说明它或定义它的范围内是可见的,而在该范围之外是不可见的。不同的标识符定义在不同的范围内有不同的作用域。按作用域的大小可分为:

程序级:包含着组成该程序的所有文件。

文件级:仅在定义它的文件内。

函数级:在它所定义的函数体内。

块级(语句):定义在分程序中、语句块内。11/21/202282函数与预处理标识符的作用域(scope)规则规则为:不同的标识符定义在不#include<iostream.h>inta=1;voidmain(){

intx=3;//doublex(3.5);error inty(5);

if(x>2) {

intx(4); cout<<x<<"\t"<<y<<"\t";

温馨提示

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

评论

0/150

提交评论