第7章函数省公共课一等奖全国赛课获奖课件_第1页
第7章函数省公共课一等奖全国赛课获奖课件_第2页
第7章函数省公共课一等奖全国赛课获奖课件_第3页
第7章函数省公共课一等奖全国赛课获奖课件_第4页
第7章函数省公共课一等奖全国赛课获奖课件_第5页
已阅读5页,还剩39页未读 继续免费阅读

下载本文档

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

文档简介

第7章函数第1页本章主要内容1函数概述2函数定义3函数参数与调用4递归函数5内联函数6重载函数7默认参数函数8全局变量与局部变量9变量存放类型10内部函数与外部函数11怎样运行一个多文件程序第2页7.1函数概述程序通常是非常复杂而冗长。实际编程中,有些程序需要几万甚至几百万行代码。在编写一个很长程序时,能够采取一个很好策略,就是把这个大程序分割成一些相对独立而且便于管理和阅读小块程序。这么,不论对程序员还是其它阅读者都很方便。把相关语句组织在一起,并给它们注明对应名称,利用这种方法把程序分块,这种形式组合就是函数。函数使用是经过函数调用实现。程序员编写完成指定任务函数,普通称之为用户自定义函数;C++提供能够在任何程序中使用公共函数,称为标准库函数。程序总是从main()函数开始开启。第3页mainbacdefghhieg下列图反应了函数被调用层次关系:第4页C++函数是一个独立完成某个功效语句块,函数与函数之间经过输入参数和返回值(输出)来联络。能够把函数看作是一个“黑盒(blackbox)”,除了输入输出,其它什么也看不见。 #include<iostream.h> voidprintstar() { cout<<"**************\n"; } voidprint_message() { cout<<"functionprint_message.\n";}

voidmain() { printstar(); print_message(); printstar(); }第5页7.2函数定义定义:<返回类型>函数名(<参数表>) { 语句; }申明:<返回类型>函数名(<参数类型说明>); intmax(intx,inty);//函数原型申明 intmax(intx,inty)//函数定义 {intz; z=x>y?x:y; return(z); }C++和C语言关于函数内部申明要求有所不一样。早期也可写作:intmax(x,y)intx,y;第6页C++中函数申明又称为函数原型。函数原型和函数定义在返回类型、函数名和参数表上必须完全一致。函数原型中无须包含参数名字,而只要包含参数类型。比如上例中函数申明能够写作: intmax(int,int);函数普通应该先申明,后使用。但假如被调用函数定义出现主调用函数之前,则能够无须加以申明。 doubleadd(doublex,doubley) { returnx+y; }

voidmain() { cout<<add(1.0,2.0); }第7页对于标准库函数(简称库函数)来说,编译器从来不把其实际定义代码看成是程序组成部分。在头文件中包含函数申明都是函数原型。C++不允许函数定义嵌套,即在函数定义中再定义一个函数是非法。假如函数原型不正确,编译器会及时汇报错误。比如,对于以上定义max函数,假如调用写成: intc; c=max(5,6,46);则编译器会汇报一个“函数调用中碰到过多函数参数”错误。又如,以下代码中,函数原型与函数定义不一致:第8页 voidfuncA(int,float);//函数原型申明 voidmain() {inta; floatb; funcA(a,b); } voidfuncA(int,int) { //… }该代码能够正确经过编译,因为函数原型与函数调用相吻合。但在链接时,找不到与函数申明相一致函数定义,结果产生“不能确定外部函数”链接错误。第9页函数返回值也称为函数值,在函数申明时约定其数据类型。 intmax(intx,inty);//函数原型申明 intmax(intx,inty)//函数定义 {intz; z=x>y?x:y; return(z); }假如返回其它数据类型,则在返回时,先作类型转换,如: intf() { return3.5; }第10页函数返回不是函数本身,而不一个值。无返回函数也能够使用return,但不能返回值。比如: voidmessage(inta) { if(a>10) return; //… }函数返回值若是省略,则默认为int类型。关于main函数及其返回值。第11页7.3函数参数与调用7.3.1形式参数和实际参数形式参数:定义函数中参数变量名实际参数:调用一个函数时,函数名后面括号中表示式 (如:变量、常量…)#include<iostream.h>intmax(inta,intb);{ returna>b?a:b;}voidmain(){ intx,y; cin>>x>>y; cout<<"max="<<max(x,y);}第12页相关说明:1)形参:在函数被调用时才分配内存,在调用结束后,形参所占用内存空间也被释放;2)实参:能够是变量、常量和表示式,但要求它们有确定值;3)实参加形参类型应相同或赋值兼容;4)C++语言要求实参变量对形参变量数据传递是“值传递”,即单项传递,只能由实参传递给形参,而不能由形参传回来给实参。函数调用结束后,形参单元被释放,实参单元仍维持原值不变。第13页7.3.2函数调用函数调用普通形式为: 函数名(实参)按函数在程序中出现位置来分,能够有以下三种函数调用方式:1)函数语句,把函数调用作为一个语句,如: printstar();2)函数表示式,如: c=2*max(a,b);3)函数参数,如: m=max(a,max(b,c));在函数调用之前,一定要确保函数已经申明过。第14页7.4递归函数7.4.1什么是递归函数(recursivefunction)递归函数即自调用函数,在函数体内部直接或间接地自己调用自己,即函数嵌套调用是函数本身。以下面程序求n! intfact(intn) { if(n==1) return1; returnfact(n-1)*n; }第15页7.4.2递归调用形式递归调用有直接递归调用与间接递归调用两种形式:intfib(intx){if(x>2)return(fib(x-1)+fib(x-2));elsereturn1;}intfn1(inta){intb;b=fn2(a+1);//...}intfn2(ints){intc;c=fn1(s-1);//...}第16页7.4.3递归调用条件(1)必须有完成函数任务语句;(2)一个确定是否能防止递归调用测试;(3)一个递归调用语句;(4)先测试,后递归调用。 intfact(intn) { if(n==1) return1; returnfact(n-1)*n; }第17页7.4.4递归评价大多数递归函数都能用非递归函数来代替,递归目标是简化程序设计,使程序易读。但递归增加了系统开销,时间上说,执行调用与返回额外工作要占用CPU时间。空间上,伴随每递归一次,栈内存就多占用一截。对应非递归函数即使效率高,但却比较难编程,而且相对来说可读性差。当代程序设计目标主要是可读性好,所以勉励用递归函数实现程序思想。第18页7.5内联函数内联函数主要用于处理程序运行效率问题。因为函数调用需要建立栈内存环境,进行参数传递,并产生程序执行转移,这些工作都需要一些时间开销。所以对于函数使用频率高,代码很短函数能够使用内联函数。定义内联函数时,在函数申明前加上inline关键字,如:

inlineintisnumber(charch);编译器看到到inline后,为该函数创建一段代码,在后面每次碰到该函数调用都用对应一段代码来替换。如:第19页#include<iostream.h>inlineintisnumber(charch);voidmain(){ charc=''; while(c!='q') { cin>>c; if(isnumber(c)) cout<<"youenteredadigit.\n"; else cout<<"youenteredanon-digit.\n"; }}intisnumber(charch){ return(ch>='0'&&ch<='9')?1:0;}第20页内联函数中,不能含有复杂结构控制语句,如switch和while。假如内联函数有这些语句,则编译将该函数视同普通函数那样产生函数调用代码。另外,递归函数是不能做为内联函数。内联函数只适合于只有1~5行小函数。对于一个含有许多语句大函数,函数调用和返回开销相对来说微不足道,所以也没有必要用内联函数实现。第21页7.6重载函数重载函数需要性:在C语言中,每个函数必须有其唯一名字,但有时,这会令人生厌。比如,求一个数绝对值,因为命名唯一,所以对于不一样类型需要不一样名字函数: intabs(int); longlabs(long); doublefabs(double);这几个函数所做事情是一样,都是求绝对值。对于在不一样类型上作不一样运算而又用一样名字情况,称这为重载。比如,上述3个函数申明能够改为: intabs(int); longabs(long); doubleabs(double);第22页C++用一个函数命名技术能够准确判断出应该使用哪个abs()函数: abs(-10); abs(-12.23);关于匹配重载函数次序。重载函数最少在参数个数、参数类型或参数次序上有所不一样,光靠返回值不一样则是不够,如: voidfunc(int); intfunc(int);让重载函数执行不一样功效,不是一个好编程格调。第23页7.7默认参数函数7.7.1默认参数目标通常函数调用时,要为函数每个参数给定对应实参。C++能够给函数定义默认参数值。如:voiddelay(intloops=1000);voiddelay(intloops){ if(loops==0) return; for(inti=0;i<loops;++i){//Donothing}}则调用:delay(2500); //loops设置为2500delay(); //OK,loops采取默认值1000第24页7.7.2默认参数申明默认参数只允许在函数申明中提供,函数定义中不允许默认参数:voidpoint(intx=3,inty=4);voidpoint(intx,inty){ cout<<x<<endl; cout<<y<<endl;}

第25页7.7.3默认参数次序要求假如一个函数中有多个默认参数,则默认参数应从右至左逐步定义。当调用函数时,只能向左匹配参数。如:voidfunc(inta=1,intb,intc=3,intd=4); //errorvoidfunc(inta,intb=2,intc=3,intd=4); //OK对于第2个函数申明:func(10,15,20,30); //OKfunc(); //error,a没有值func(12,12); //c,d默认Func(2,15,,20); //error,只有从右到左次序默认

第26页7.7.4默认参数与函数重载默认参数可将一系列简单重载函数合成为一个,如:voidpoint(int,int){/*...*/}voidpoint(inta){returnpoint(a,4);}voidpoint(){returnpoint(3,4);}可用下面默认参数函数来代替:voidpoint(inta=3,intb=4);

第27页而以下重载函数将会引发二义性,如:voidfunc(inta);voidfunc(inta,intb=4);voidfunc(inta=3,intb=4);func(7); //errorfunc(20,30); //error

第28页7.8全局变量与局部变量7.8.1程序内存区域并不是全部变量时时刻刻都是可知。一些变量在整个程序中都是可见,它们称为全局变量。一些变量只能在一个函数中可知,称为局部变量。第29页7.8.2全局变量在函数外边申明变量被认为是全局变量,并在程序每个函数中可见。全局变量由编译器自动建立,而且初始化为0。intn=5;voidmain(){intm=n;//…}voidfunc(){ints;n=s;//…}第30页7.8.3局部变量在函数内部定义变量仅在该函数内是可见。一个函数可认为局部变量定义任何名字,而不用担心其他函数是否使用过一样名字。局部变量没有初始化,如果局部变量不被显式初始化,那么其内容是不可预料。voidmain(){intn;//…}voidfunc(){intn;//…}第31页7.9变量存放类型7.9.1静态局部变量在局部变量前加上“static”关键字,就成了静态局部变量。静态局部变量存放在内存全局数据区。函数结束时,静态局部变量不会消失,每次该函数调用时,也不会为其重新分配空间。静态局部变量与全局变量共享全局数据区,但静态局部变量只在定义它函数中可见。示例程序:第32页#include<iostream.h>intn=0;voidfunc1();voidfunc2();voidmain(){ for(inti=0;i<2;++i) { func1(); func2(); }}voidfunc1(){ staticinta=0; n++; a++; cout<<"n="<<n<<",a="<<a<<endl;}voidfunc2(){ inta=0; n++; a++; cout<<"n="<<n<<",a="<<a<<endl;}n=1,a=1n=2,a=1n=3,a=2n=4,a=1运行结果第33页7.9.2外部变量用extern申明外部变量。外部变量(即全局变量)是在函数外部定义,它作用域为从变量定义处开始到本程序文件末尾。比如,一个工程文件由两个CPP文件组成,分别是part1.cpp和part2.cpp:第34页//////////////////////////////////////////////////////////////////////Part1.cpp////////////////////////////////////////////////////////////////////#include<iostream.h>voidfn1();voidfn2();intn;voidmain(){ n=3; fn1(); //fn1()函数定义在本文件中 cout<<n<<endl;}voidfn1(){ fn2(); //fn2()函数定义不在本文件中}//////////////////////////////////////////////////////////////////////Part2.cpp////////////////////////////////////////////////////////////////////#include<iostream.h>externintn; //n由另一个源文件定义voidfn2() //fn2()函数在另一个源文件中使用{ n=8;}第35页用extern申明外部变量是变量申明,不是变量定义。注意申明与定义区分。假如一个全局变量只限于本文件使用,不希望被其它文件引用,这时能够在定义全局变量时加一个static,如://////////////////////////////////////part1.cpp////////////////////////////////////staticintn;voidmain(){ n=3; //…}第36页7.9.3变量作用域变量作用域是变量在程序中有效范围,C++作用域分为:局部作用域(块作用域),函数原型作用域,文件作用域和类作用域。局部作用域:当标识符申明出现在由一对花括号括起来程序块内时,该标识符作用域从申明点开始,到块结束处为止,该作用域范围含有局部性。如:第37页#include<iostream.h>intn=0;doublearea(doublewidth,doublelength); //width,length可有可无voidmain(){ intsum=0; for(inti=0;i<10;i++) { inthalf; half=i/2; n+=sum; }

cout<<half<<i

<<sum<<n; //ERROR!!!}第38页7.9.4变量可见性#include<iostream.h>intn=0;voidmain(){ intn=10; cout<<"ninsidemain()is"<<n<<endl <<"noutsidemain()is"<<::n<<endl;}第39页7.10内部函数与外部函数依据函数能否被其它源文件调用,将函数区分为内部函数和外部函数。假如一个函数只能被本文件中其它函数调用,被之为内部函数。在定义内部函数时,在函数名和函数返回值类型前加上static。假如一个函数能够在其它文件中作用,称之为外部函数。定义外部函数时,在函数名和函数返回值类型前加上extern。因为函数本质上是全局,所以extern能够省略。第40页7.11怎样运行一个多文件程序一个程序经常由多个源文件组成,每个源文件是一个可编译程序单位。在将程序分解成多个源文件之后,必须计划在每个源文件中哪些信息能够被其它文件使用,哪些不能够。因为同一名字申明能够出现屡次,所以能够将申明放在头文件中。头文件起着源文件之间接口作用。比如有以下程序结构:第41页/////////////////////////////////////////////////////////////////area.h//////////////////////////////////////////////////

温馨提示

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

评论

0/150

提交评论