C++程序设计基础教程 第2版 课件 第4章 函数_第1页
C++程序设计基础教程 第2版 课件 第4章 函数_第2页
C++程序设计基础教程 第2版 课件 第4章 函数_第3页
C++程序设计基础教程 第2版 课件 第4章 函数_第4页
C++程序设计基础教程 第2版 课件 第4章 函数_第5页
已阅读5页,还剩51页未读 继续免费阅读

下载本文档

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

文档简介

第4章函数主要内容4.1 概述4.2 函数定义与函数声明4.3 函数的调用4.4 函数重载4.5 函数模板4.6 函数的嵌套调用4.7 递归函数4.8 存储类别4.9 作用域4.10 内部函数和外部函数4.11 预处理指令4.12 应用实例4.1概述函数调用关系示意图4.2函数定义与函数声明4.2.1函数的定义返回值类型函数名([形式参数表]){

语句序列}//sumSeries函数定义intsumSeries(intstart,intend){ intresult=0; for(inti=start;i<=end;i++) result+=i; returnresult;}函数的返回值(1)函数的返回值通过return语句获得。(2)如果函数类型和return语句中表达式的值不一致,则以函数类型为准,对数值型数据将自动进行类型转换。(3)当一个函数没有返回值时,返回类型必须用void说明,这时函数体中可以没有return语句,也可以有return语句,但return后没有表达式,其形式如下所示:

return;引例:#include<iostream>usingnamespacestd;intmain(){floata,b,c;cin>>a>>b;c=add(a,b);cout<<″sum=″<<c<<endl;return0;}floatadd(floatx,floaty)//定义add函数{floatz;z=x+y;return(z);}floatadd(floatx,floaty);//对add函数作声明4.2.2函数声明与函数原型所谓函数声明(declare),就是在函数尚在未定义的情况下,事先将该函数的有关信息通知编译系统,以便使编译能正常进行。函数原型告诉编译器该函数的返回类型、函数名和形参表。按如下形式声明函数原型:返回值类型函数名([形参表]);注意:对函数的定义和声明不是同一件事情。定义是完整的函数,包括函数名、返回值类型、形参及其类型、函数体。声明则只是把函数名、返回值类型以及形参的类型、个数和顺序通知编译系统(注意,不包括函数体)。函数原型函数声明也称为函数原型(functionprototype)。使用函数原型是C和C++的一个重要特点。函数原型的一般形式为:(1)函数类型函数名(参数类型1,参数类型2…);(2)函数类型函数名(参数类型1参数名1,参数类型2参数名2…);

其实,在函数声明中也可以不写形参名,而只写形参的类型,如:floatadd(float,float);4.3函数的调用调用一个函数就是执行该函数的函数体。4.3.1函数调用的概念函数调用的一般形式为:

函数名([实参表])形式参数和实际参数在定义函数时函数名后面括号中的变量名称为形式参数(formalparameter,简称形参)。在主调函数中调用一个函数时,函数名后面括号中的参数(可以是一个表达式)称为实际参数(actualparameter,简称实参)。4.3.2函数的传值调用【例】被调函数试图修改实参的值#include<iostream>usingnamespacestd;voidinterchange(int,int); //interchange函数原型声明intmain(){ intm=10,n=20; cout<<"调用函数之前(实参):"<<"m="<<m<<",n="<<n<<endl; interchange(m,n);//interchange函数调用 cout<<"调用函数之后(实参):"<<"m="<<m<<",n="<<n<<endl; return0;}实参voidinterchange(intx,inty)//interchange函数定义{ cout<<"交换之前(形参):"<<"x="<<x<<",y="<<y<<endl; inttemp; temp=x; x=y; y=temp; cout<<"交换之后(形参):"<<"x="<<x<<",y="<<y<<endl;}形参有关形参与实参的说明:(1)形参只有在函数调用时,才被分配内存单元;调用结束后,形参所占的内存单元即被释放。(2)实参可以是常量、变量或表达式,如

max(3,a+b);(3)实参与形参的类型应相同或赋值兼容。(4)实参变量对形参变量的数据传递是“值传递”,即单向传递。4.4为形参指定默认值所谓默认值参数(简称默认参数)是指在编写函数时为形参提供一个默认值,用户在调用函数时,如果在对应的参数位置上没有指定实参值,则系统采用默认值作为函数实参。#include<iostream>#include<cmath>usingnamespacestd;doubledist(doublex1,doubley1,doublex2=0,doubley2=0);intmain(){ doublex1,y1,x2,y2; cout<<"请输入第一个点的坐标:"; cin>>x1>>y1; cout<<"请输入第二个点的坐标:"; cin>>x2>>y2; cout<<"("<<x1<<","<<y1<<")到("<<x2<<","<<y2<<")的距离是:" <<dist(x1,y1,x2,y2)<<endl; //指定所有实参值 cout<<"("<<x1<<","<<y1<<")到("<<x2<<","<<0<<")的距离是:" <<dist(x1,y1,x2)<<endl; //使用部分默认值值,y2使用默认值0 cout<<"("<<x1<<","<<y1<<")到("<<0<<","<<0<<")的距离是:" <<dist(x1,y1)<<endl; //使用所有默认值,x2,y2均使用默认值0 return0;}doubledist(doublex1,doubley1,doublex2,doubley2){ returnsqrt(pow(x1-x2,2)+pow(y1-y2,2));}有关默认参数的说明:(1)C++规定,默认参数必须是函数参数表中最右边(尾部)的参数。也就是说,在默认参数的右边,不能再出现非默认参数,例如:doubledist(doublex1=0,doubley1,doublex2,doubley2=0)//错误,y1和x2是非默认参数(2)默认值可以是常量、全局变量或函数调用,但不能是局部变量。(3)指定参数的默认值可以在函数定义中进行,也可以在函数原型中进行,通常是在函数名第一次出现时指定。若已经在函数原型中指定默认参数,则函数定义时不能重复指定。4.5函数重载所谓重载,其实就是“一名多用”。C++允许在同一范围中声明几个功能类似的同名函数,但是这些函数的形式参数(指参数的个数、类型)必须不同,这就是所谓的函数重载(functionoverloading)。【例】使用函数重载计算不同类型(char、int、double)数据中的大值。#include<iostream>usingnamespacestd;intmain(){ charmaxValue(char,char);//函数原型 intmaxValue(int,int); //函数原型 doublemaxValue(double,double);//函数原型 doublemaxValue(double,double,double);//函数原型 cout<<"maxValue('a','A')='"<<maxValue('a','A')<<endl; cout<<"maxValue(97,65)="<<maxValue(97,65)<<endl; cout<<"maxValue(23.1,78.5)="<<maxValue(23.1,78.5)<<endl; cout<<"maxValue(23.1,78.5,-200.96)="<<maxValue(23.1,78.5,-200.96)<<endl; return0;}charmaxValue(charx1,charx2)//获取两个char型数据的大值{ returnx1>=x2?x1:x2; }intmaxValue(intx1,intx2)//获取两个int型数据的大值{ returnx1>=x2?x1:x2; }doublemaxValue(doublex1,doublex2)//获取两个double型数据的大值{ returnx1>=x2?x1:x2; }doublemaxValue(doublex1,doublex2,doublex3)//获取三个double型数据的大值{ returnmaxValue(maxValue(x1,x2),x3);

//调用了带有两个double型参数的maxValue函数}4.6函数模板所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟类型来代替。凡是仅是形参类型不同的函数都可以用这个模板来代替,不必重复定义多个函数。在调用函数时系统会根据实参类型来取代模板中的虚拟类型,从而实现不同的功能。【例4-7】将【例4-6】程序改为通过函数模板来实现。

#include<iostream>usingnamespacestd;template<typenameT> //模板声明,其中T为类型参数(虚拟类型名)TmaxValue(Tx1,Tx2)//定义一个通用函数,用T作虚拟类型名{ returnx1>=x2?x1:x2;}intmain(){ cout<<"maxValue('a','A')='"<<maxValue('a','A')<<endl; cout<<"maxValue(97,65)="<<maxValue(97,65)<<endl; cout<<"maxValue(23.1,78.5)="<<maxValue(23.1,78.5)<<endl; cout<<"maxValue(23.1,78.5,-200.96)="

<<maxValue(maxValue(23.1,78.5),-200.96)<<endl; return0;}4.6嵌套调用

C++不允许对函数作嵌套定义,也就是说在一个函数中不能完整地包含另一个函数。在一个程序中每一个函数的定义都是互相平行和独立的。

C++不能嵌套定义函数,但可以嵌套调用函数。

#include<iostream>#include<cmath>usingnamespacestd;doublef(double); //f函数原型doubleg(double,double);//g函数原型intmain(){ cout<<"g(2.5,3.4)="<<g(2.5,3.4)<<endl; return0;}doubleg(doublex,doubley){ if(x<=y)returnf(x+y)/(f(x)+f(y)); elsereturnf(x-y)/(f(x)+f(y));}doublef(doublet){ return(1+exp(-t))/(1+exp(t));}4.8

递归函数C++允许函数直接或间接地调用自己。这种直接调用自己或者借助于其它函数间接调用自己的函数称为递归函数(recursivefunction)。

直接递归间接递归

【例】用递归方法求n!。

求n!可以用递推方法,即从1开始,乘2,再乘3……一直乘到n。求n!也可以用递归方法,即5!=4!×5,而4!=3!×4,…,1!=1。可用下面的递归公式表示:

n!= 1

(n=0,1)

n·(n-1)! (n>1)【例4-9】用递归的方法求5!。#include<iostream>usingnamespacestd;intmain(){ longfac(int);//函数原型声明

cout<<"5!="<<fac(5)<<endl;//函数调用

return0;}longfac(intn)//函数定义{longc;if(n==0||n==1)c=1;elsec=n*fac(n-1); //递归函数调用returnc;}递归算法的编写和执行过程递归算法的编写1)将问题用递归的方式描述(定义)2)根据问题的递归描述(定义)编写递归算法

递归定义包括两项基本项(终止项):描述递归终止时问题的求解;递归项:将问题分解为与原问题性质相同,但规模较小的问题;

例:n!的递归定义基本项:n!=1当n=0,1

递归项:n!=n(n-1)!

当n>14.9变量的作用域与生存期变量的特性:(1)变量的作用域指的是变量可被引用的空间范围。(2)变量的生存期指的是变量存续的时间范围,从系统为变量分配内存空间开始,到系统收回空间为止。(1)块作用域(局部作用域)程序块:用一对花括号括起来的语句,函数体也是一个块,一个控制结构语句也构成一个块。在程序块中声明的标识符具有块作用域。该标识符的作用域从声明处开始,到所在块结束处为止。(2)函数原型作用域是C++中最小的作用域,指在函数原型声明时形参的作用范围(开始于函数原型声明的左括号以后的形参定义处,结束于函数原型的右括号处)。(3)文件作用域在函数和类之外声明的标识符(即全局变量)具有文件作用域,其作用范围从声明处开始,到所在文件结束处为止。floatf1(inta) {intb,c;┆}charf2(intx,inty) {inti,j; ┆}intmain() {intm,n;┆{intp,q;┆}}p、q在复合语句中有效b、c有效a有效i、j有效x、y有效m、n有效局部变量(localvariable):函数内部定义的变量复合语句中定义的变量全局变量(globalvariable)在所有函数之外定义的变量全局变量的有效范围为从定义变量的位置开始到本源文件结束。局部变量和全局变量intp=1,q=5;

floatf1(inta){intb,c;┆}charc1,c2;

charf2(intx,inty){inti,j;┆}intmain(){intm,n;┆}全局变量c1、c2的作用范围全局变量p、q的作用范围4.10变量的存储类别存储类别指的是数据在内存中存储的方法。内存中的供用户使用的存储空间的情况:代码区全局数据区栈区堆区存储类别描述符意义存储类别描述符意义auto自动变量extern外部变量register寄存器变量static静态变量存储类别描述符及其意义4.10.1自动变量自动变量用auto声明。C++规定:函数中的局部变量,如果不显式声明存储类别,均默认为自动变量,即自动变量可以省去描述符auto。例如:intfun(inta)//形参a为int型自动变量{autointb,c=3;//b和c均为int型自动变量

doubled,e;//d和e均为double型自动变量

……}4.10.3用extern声明全局变量extern:扩展全局变量的作用域。(1)在一个文件内声明全局变量如果全局变量不在文件的开头定义,又想在定义之前的函数里使用该全局变量,则应该在引用之前用关键字extern对该变量作全局变量声明,表示该变量是一个将在后面定义的全局变量。【例4-11】用extern对全局变量作提前引用声明,以扩展其作用域。#include<iostream>usingnamespacestd;intmaxValue(int,int);intmain(){ externinta,b; cout<<maxValue(a,b)<<endl; return0;}inta=15,b=7;//定义全局变量a,b,第9行intmaxValue(intx,inty){

return(x>y?x:y);}(2)在多文件的程序中声明全局变量4.10.4静态变量静态变量(staticvariable)存储在全局数据区,占有的存储空间要到整个程序结束时才释放。(1)静态局部变量局部变量定义时前面加上“static”关键字,就成了静态局部变量。【例4-9】静态局部变量的值。#include<iostream>usingnamespacestd;intincrease();intmain(){ for(inti=0;i<3;i++) cout<<"第"<<i+1<<"次调用的返回值:"<<increase()<<endl; return0; }intincrease(){ intx=0;//自动局部变量 staticinty=0;//静态局部变量 x++; y++; returnx+y; }表4-1调用函数时自动局部变量和静态局部变量的值调用次数调用开始时的值调用结束时的值函数返回值自动变量x静态局部变量y自动变量x静态局部变量y第1次00112第2次01123第3次02134(2)静态全局变量

有时在程序设计中希望某些外部变量只限于被本文件引用,而不能被其他文件引用。这时可以在定义外部变量时加一个static声明。例如:

file1.cppfile2.cppstaticinta=3;inta;intmain()intfun(intn){{┆┆a=a*n;┆}}4.11内部函数和外部函数4.11.1内部函数只能在定义它的文件中被调用的函数,称为内部函数,

温馨提示

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

评论

0/150

提交评论