《面向对象第四章精选文档.ppt》由会员分享,可在线阅读,更多相关《面向对象第四章精选文档.ppt(90页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、面向对象课件第四章本讲稿第一页,共九十页第四章第四章 函数函数 4.14.1 函数概述函数概述 4.24.2 函数的定义和声明函数的定义和声明 4.34.3 函数的调用函数的调用 4.44.4 参数传递参数传递 4.54.5 标识符的作用域标识符的作用域 4.64.6 变量的生存期变量的生存期 4.74.7 递归函数递归函数 4.84.8 C+的库函数的库函数本讲稿第二页,共九十页4.14.1 函数概述函数概述c+函数特点:函数特点:w独立完成某个功能的语句块w封装了程序代码和数据,实现了更高级的抽象w减少代码重复,提高程序的可重用性本讲稿第三页,共九十页4.14.1 函数概述函数概述w 函数
2、的几个例子函数的几个例子例1:int bigger(int a,int b)return (ab)?a:b;/找出最大数获取参数并返回值本讲稿第四页,共九十页4.14.1 函数概述函数概述例2:void delay(long a)for(int i=1;i=a;i+);/延迟一个小的时间片获取参数但不返回值本讲稿第五页,共九十页4.14.1 函数概述函数概述例3:int geti()int x;coutx;return x;/从键盘上获取一个整数不获取参数但返回值本讲稿第六页,共九十页4.14.1 函数概述函数概述例4:void message()cout“This is a message.
3、n”;/在屏幕上显示一条消息不获取参数也不返回值本讲稿第七页,共九十页4.2 4.2 函数的定义和声明函数的定义和声明 函数结构函数结构w 函数头+函数体返回值返回值 函数名函数名(参数表参数表)函数体函数体 本讲稿第八页,共九十页4.2 4.2 函数的定义和声明函数的定义和声明 函数结构函数结构答疑答疑函数:询问老师函数:询问老师参数:询问的题目参数:询问的题目返回:答案返回:答案动作:解答题目动作:解答题目订餐订餐函数:订餐函数:订餐参数:订的菜单参数:订的菜单返回:是或否返回:是或否动作:做菜并送到家动作:做菜并送到家本讲稿第九页,共九十页4.2 4.2 函数的定义和声明函数的定义和声明
4、w 函数的定义函数的定义一般形式:类型类型 函数名函数名(形参表形参表)语句组语句组 注:注:1.默认的函数类型是int 2.不允许函数定义嵌套本讲稿第十页,共九十页4.2 4.2 函数的定义和声明函数的定义和声明w不允许函数定义嵌套如:void main()int func()函数独立完成某个功能,函数与函数之间通过参数和返回值联系参参 数数-函数的输入函数的输入返回值返回值-函数的输出函数的输出本讲稿第十一页,共九十页4.2 4.2 函数的定义和声明函数的定义和声明w 函数的声明(即函数原型)函数的声明(即函数原型)返回类型返回类型 函数名函数名(参数表参数表);w函数原型的作用:声明了函
5、数的参数情况及返回值本讲稿第十二页,共九十页4.2 4.2 函数的定义和声明函数的定义和声明说明:1、函数原型是一条程序语句,须以分号结尾2、函数原型的参数表中可只包含参数的类型如:int area(int,int);int area(int length,int width);左边也是合法的,只关心参数的个数和类型本讲稿第十三页,共九十页4.2 4.2 函数的定义和声明函数的定义和声明函数的定义和函数声明的关系函数的定义和函数声明的关系#include#include void main()double x;coutsin(x);函数原型double sin(double);本讲稿第十四页,
6、共九十页4.2 4.2 函数的定义和声明函数的定义和声明w函数的定义与声明的关系函数的定义与声明的关系 void main()func();void func()void func();void main()func();void func()本讲稿第十五页,共九十页4.2 4.2 函数的定义和声明函数的定义和声明w 函数声明的原则:函数声明的原则:如果一个函数定义在先,调用在后,调用前可不必声明如果一个函数定义在后,调用在先,调用前必须声明本讲稿第十六页,共九十页4.2 4.2 函数的定义和声明函数的定义和声明w 总总 结结1、函数在使用前必须先声明或先定义2、函数的定义只有一次,但函数的声
7、明可以 出现多次3、函数的定义和声明必须在参数、返回值方 面保持一致本讲稿第十七页,共九十页4.2 4.2 函数的定义和声明函数的定义和声明w例:原型 int area(int,int);调用 c=area(10,5,8);w例:void fun(int,float);int main()int a;float b;fun(a,b);void fun(int,int)/参数个数不同参数类型不一致本讲稿第十八页,共九十页4.2 4.2 函数的定义和声明函数的定义和声明w引用本文件外的函数时,需用#include将包含该函数的文件嵌入到当前位置w#include有两种形式:形式一:#include
8、形式二:#include“文件名”形式一用于C+提供的库函数,存放在C+系统目录中的include子目录中形式二用于程序员开发的模块,存放在工作目录中本讲稿第十九页,共九十页4.3 4.3 函数的调用函数的调用1、函数的调用和返回2、函数的调用过程3、函数调用的实现栈本讲稿第二十页,共九十页4.3 4.3 函数的调用函数的调用w 函数通过调用发挥作用w 在面向对象思想中,函数调用成为对象之间 发送消息的工具int A()B();int classA:A()classB:B();本讲稿第二十一页,共九十页4.3 4.3 函数的调用函数的调用 函数调用语句函数名函数名(参数表参数表);参数表,由个
9、,个或多个实际参数组成实参的个数由形参决定,调用函数时实参给形参初始化实参对形参初始化是按其位置对应进行本讲稿第二十二页,共九十页4.3 4.3 函数的调用函数的调用 函数的返回函数返回的条件:函数返回的条件:执行到函数的最后一条语句 遇到return语句(语句格式如下)return ;或return;本讲稿第二十三页,共九十页4.3 4.3 函数的调用函数的调用w return;语句的实现过程;语句的实现过程1 1、先计算出表达式的值;2 2、当表达式类型与函数类型不同时,将表达 式的类型自动、强制性地转换为函数的类型,可能出现不保值的情况3 3、将表达式的值返回给调用函数4 4、将程序执行
10、的控制权由被调函数转向调用函数,执行调用函数后面的语句本讲稿第二十四页,共九十页4.3 4.3 函数的调用函数的调用w return;语句语句无返回值,只返回程序执行的控制权w 对于无返回值的函数须用void来说明类型w 在函数中return;语句可有可无w 若没有return;语句,执行到函数体的最后 一条语句时返回调用函数本讲稿第二十五页,共九十页4.3 4.3 函数的调用函数的调用 main函数函数wmain函数是由系统调用的第一个函数wmain函数直接或间接调用程序中所有其他函数wmain函数的参数通过命令行提供:如:copy arg1 arg2wmain函数返回值给调用它的系统(0为
11、正常返回,1为异常返回)wmain函数默认的类型是int本讲稿第二十六页,共九十页4.3 4.3 函数的调用函数的调用函数的调用过程main()a();a()b();b()本讲稿第二十七页,共九十页4.3 4.3 函数的调用函数的调用3.函数调用的实现函数调用的实现-栈栈w 栈中存放的内容:-调用函数的返回地址 -传递参数 -被调用函数的局部变量参数2 返回地址 参数1 局部变量本讲稿第二十八页,共九十页4.3 4.3 函数的调用函数的调用函数调用过程:函数调用过程:首先建立被调用函数的栈空间;保护调用函数的运行状态和返回地址 传递函数实参给形参;执行被调用函数的函数体内语句;将控制权转交给调
12、用函数本讲稿第二十九页,共九十页4.3 4.3 函数的调用函数的调用函数调用时栈的变化过程main()a()b()C()main()main()main()a()main()a()b()main()a()b()main()a()本讲稿第三十页,共九十页4.3 4.3 函数的调用函数的调用函数调用的实现函数调用的实现栈栈说明:说明:w 函数的局部变量是临时存放的w 栈空间是有限的本讲稿第三十一页,共九十页4.4 4.4 参数传递参数传递w 参数传递方式参数传递方式w 传值调用传值调用w 设置参数的默认值设置参数的默认值本讲稿第三十二页,共九十页4.4 4.4 参数传递参数传递w参数传递方式:参数
13、传递方式:传值调用单向:调用函数 传址调用(c语言中没有传址调用)双向:调用函数被调用函数 实参 形参被调用函数 实参 形参本讲稿第三十三页,共九十页4.4 4.4 参数传递参数传递C+变量的值有两种变量的值有两种变量本身本身值 (传值调用)变量地址地址值 (传址调用)用指针实参:实参:常量、变量值、表达式值形参:形参:变量 本讲稿第三十四页,共九十页4.4 4.4 参数传递参数传递w传值调用的实现传值调用的实现函数调用时,系统先计算实参的值,再将实参的值按位置对应赋给形参。w传值调用的实现机制传值调用的实现机制系统将实参拷贝一个副本(存放在被调用函数的栈中)给形参。w传值调用的特点传值调用的
14、特点形参值的改变不影响实参。本讲稿第三十五页,共九十页例:#includevoid swap(int,int);void main()int a=5,b=9;swap(a,b);cout“a=“a“,”“b=“bendl;void swap(int x,int y)int temp;temp=x;x=y;y=temp;cout“x=“x“,”“y=“yendl;本讲稿第三十六页,共九十页w 程序运行结果:x=9,y=5a=5,b=9由执行结果可知:实参的值没有改变本讲稿第三十七页,共九十页4.4 4.4 参数传递参数传递w设置参数的默认值当需要使用相同的实参反复调用某函数时,c+允许给参数设置
15、默认值例:int fun(int a,int b=5,int c=8);fun函数的三个参数中,有两个设置了默认值本讲稿第三十八页,共九十页4.4 4.4 参数传递参数传递w例:void delay(int loops)if(loops=0)return;for(int i=0;iloops;i+);函数声明:void delay(int loops=1000);函数调用:delay(2500);delay();/loops使用默认值1000本讲稿第三十九页,共九十页4.4 4.4 参数传递参数传递在设置和使用默认参数时应注意:在设置和使用默认参数时应注意:默认参数在函数声明中提供,当只有函数
16、定义时,默认参数才可出现在函数定义中 一个函数的多个参数中,既有默认值也有非 默认值时应将默认值放在参数表的最右端。如:int fun(int i=8,char c,int j=45);/error!本讲稿第四十页,共九十页4.4 4.4 参数传递参数传递 函数调用时,给定的实参值将取代参数的默认值,没有给定实参值将使用默认值 默认参数即可以是数值,也可以是表达式本讲稿第四十一页,共九十页4.4 4.4 参数传递参数传递w例:分析程序的执行结果#includevoid fun(int a=1,int b=2,int c=3)cout“a=“a“,b=”b“,c=”cendl;void main
17、()fun();fun(9);fun(4,5);fun(7,8,9);执行结果:执行结果:a=1,b=2,c=3a=9,b=2,c=3a=4,b=5,c=3a=7,b=8,c=9本讲稿第四十二页,共九十页4.4 4.4 参数传递参数传递例:#includeint q=5,p=7;int sum_int(int a,int b=q+p,int c=q*p);void main()int x=5,y=10;int s1=sum_int(x);int s2=sum_int(x,y);cout“s1=”s1n“s2=“s2endl;int sum_int(int i,int j,int k)retur
18、n i+j+k;本讲稿第四十三页,共九十页4.54.5 标识符的作用域标识符的作用域w 作用域是指标识符的作用范围在C+程序中出现的各种标识符,都有着不同的作用域w标识符的作用域规则:标识符只能在说明它或定义它的范围内是可见的(可进行存取或访问操作)本讲稿第四十四页,共九十页4.5 4.5 标识符的作用域标识符的作用域w作用域的种类作用域的种类种种 类类作用域作用域程序级组成该程序的所有文件文件级从定义的地方起到文件结束函数级函数体内。包括形参、函数内定义的变量块 级从定义的地方起到相应的块尾包括if、swicth、循环中定义的 变量w作用域最大的是程序级,最小的是块级本讲稿第四十五页,共九十
19、页4.5 4.5 标识符的作用域标识符的作用域w例:int global,i;void fun1(int para1,int para2)int local1,local2,j;if(para1=para2)int k;int fun2()K块域local1,local2,j函数域global,i文件域本讲稿第四十六页,共九十页4.5 4.5 标识符的作用域标识符的作用域关于重新定义标识符的作用域规定关于重新定义标识符的作用域规定w在同一作用域内,不能有同名变量存在w在不同的作用域内,允许定义同名变量本讲稿第四十七页,共九十页4.5 4.5 标识符的作用域标识符的作用域w例:void fun(
20、)int a;float a;float a;/非法/合法注:注:块内的块内的float a在块内可见,在块内可见,且存在且存在 int a在块内不可见在块内不可见,但存在但存在本讲稿第四十八页,共九十页w例:分析下列程序的输出结果#includevoid main()int a=5,b=7,c=10;couta“,”b“,”cendl;int b=8;float c=8.8;couta“,”b“,”cendl;a=b;int c;c=b;couta“,”b“,”cendl;couta“,”b“,”cendl;couta“,”b“,”cendl;运行结果:5,7,105,8,8.88,8,88
21、,8,8.88,7,10本讲稿第四十九页,共九十页w例:分析下列程序的输出结果#includevoid main()int i=5;for(;i0;i-)int i=25;coutit;coutn in;程序执行结果:25 25 25 25 25 0本讲稿第五十页,共九十页4.5 4.5 标识符的作用域标识符的作用域w局部变量与全局变量局部变量与全局变量在函数内或块内定义的变量为局部变量局部变量在文件内或程序内定义的变量为全局变量全局变量局部变量的特点:局部变量的特点:提高函数的独立性和安全性全局变量的特点:全局变量的特点:可作为函数之间通信的一种方 式,但这种方式是不安全的,不建议使用。本讲
22、稿第五十一页,共九十页4.5 4.5 标识符的作用域标识符的作用域w函数之间的通信方式有两种:参数传递和返回值 使用全局变量在软件开发中,应尽量用参数传递取代全局变量,少用或不用全局变量本讲稿第五十二页,共九十页w例:演示局部变量与全局变量(书上96页程序4.4.1)#includevoid func1();void func2();void main()cout“No variables defined in mainn”;func1();int age;void func1()age=45;cout“Age in func1()is”agen;func2();void func2()cou
23、t“Age in func2()is”agen;/问题:int age;移到不同位置时,其结果如何?本讲稿第五十三页,共九十页4.64.6 变量的生存期变量的生存期w 变量的存储类型w C+程序的存储组织w auto和register变量w extern变量w static变量本讲稿第五十四页,共九十页4.64.6 变量的生存期变量的生存期w变量的存储类型变量的存储类型C+变量除有数据类型外还有存储类型数据类型:数据类型:决定变量的存储方式,取值范围,可进行的操作存储类型:存储类型:决定变量的生存期,分配内存的 方式,初始化情况本讲稿第五十五页,共九十页4.64.6 变量的生存期变量的生存期w
24、变量具有下列四种存储类型之一:auto自动型register寄存器型static静态型extern外部型修饰局部变量修饰局部、全局变量本讲稿第五十六页,共九十页4.64.6 变量的生存期变量的生存期w变量的存储类型在定义变量时声明w格式:存储类型存储类型 数据类型数据类型 变量名;变量名;例:auto int i;static char c;w 默认存储类型:局部变量 auto全局变量 extern本讲稿第五十七页,共九十页4.64.6 变量的生存期变量的生存期w C+程序的存储组织内存分布:C+将内存分为四个部分程序代码程序代码程序数据程序数据堆堆栈栈静态区静态区动态区动态区全局变量全局变量
25、静态变量静态变量动态申请的变量动态申请的变量局部变量局部变量静态局部变量静态局部变量静态全局变量静态全局变量本讲稿第五十八页,共九十页4.64.6 变量的生存期变量的生存期w静态区:静态区:该区内的变量具有全局寿命 初始化为0,且只初始化一次w动态区:动态区:程序运行过程中根据需要动态分配与 释放内存空间 必须初始化,否则初始化值随机本讲稿第五十九页,共九十页4.64.6 变量的生存期变量的生存期w例:int i;/局部变量couti;/未初始化就使用(垃圾值)输出结果:输出结果:-26956 一个程序两次调用同一个函数,分配给该函数中局部变量的内存地址可能是不同的本讲稿第六十页,共九十页4.
26、64.6 变量的生存期变量的生存期w例:int sum;/sum没有确定值 for(int i=1;i=10;i+)sum+=i;coutsumendl;w 求和的值是无意义的w 应将 int sum;改为 int sum=0;本讲稿第六十一页,共九十页4.64.6 变量的生存期变量的生存期wauto 和和 register 变量变量特点:只修饰局部变量 局部寿命(生命期与作用域一致)必须初始化或赋值后才能使用 (没有默认值)本讲稿第六十二页,共九十页4.64.6 变量的生存期变量的生存期wauto 与与 register 的区别的区别 register 的存取速度比auto快 缺省是auto
27、 (因此,局部变量一般不指定存储类型)本讲稿第六十三页,共九十页4.64.6 变量的生存期变量的生存期wextern 变量变量特点:特点:全局寿命(作用域最大,是整个程序)extern变量的定义和说明是两回事,只能定义一次,可以说明多次 定义时,可省略extern,应定义在函数 体之外,可出现在程序头、中、尾本讲稿第六十四页,共九十页4.64.6 变量的生存期变量的生存期 说明时,须加extern,下列情况必须说明:同一文件中的外部变量,如果定义在后,引用在先,引用前必须说明 在程序的一个文件中定义的外部变量,要在程序中的另一个文件中引用,则引 用前必须说明 外部变量定义后,具有默认值:int
28、型为0,char型为空,浮点型为0.0本讲稿第六十五页,共九十页w例:#includevoid main()extern int a;int fun(int);int y=fun(a);coutyendl;int a=5;int fun(int x)int b=6;return (a+b)*x;/说明外部变量a,因为a的定义在后/定义外部变量a,作用域是整个程序/b是auto型,作用域是fun()函数内/y是auto型,作用域是main()函数内/程序执行结果:55本讲稿第六十六页,共九十页4.64.6 变量的生存期变量的生存期wstatic变量变量特点:特点:说明或定义时,须加static
29、分为静态局部变量和静态全局变量 作用域与生命期不一致 定义或说明后具有默认值(同extern)本讲稿第六十七页,共九十页4.64.6 变量的生存期变量的生存期w静态变量可分为:静态变量可分为:静态局部变量和静态全局变量静态局部变量和静态全局变量w二者的区别:二者的区别:静态局部变量:定义在函数体内或程序块内静态局部变量:定义在函数体内或程序块内静态全局变量:定义在函数体外静态全局变量:定义在函数体外本讲稿第六十八页,共九十页4.64.6 变量的生存期变量的生存期w静态局部变量:作用域是在定义它的函数体内或程序块内,而生命期是整个程序(作用域内可见且存在,作用域外不可见但存在)本讲稿第六十九页,
30、共九十页4.64.6 变量的生存期变量的生存期w静态局部变量与静态局部变量与auto变量的区别:变量的区别:auto变量的作用域与生命期一致 auto变量每次调用,被重新初始化,static变量每次调用都保留改变后的值w例:静态变量用于调用计数void CountFun()static int count=0;count+;cout“You have called me“count“times!”;本讲稿第七十页,共九十页4.64.6 变量的生存期变量的生存期w静态全局变量静态全局变量作用域作用域是在定义或说明它的文件中,从定义或说明处开始到文件尾生命期生命期是整个程序本讲稿第七十一页,共九十
31、页w例:分析程序执行结果#includevoid main()int a=3;static int b;/静态局部变量b+=fun(a);cout“a=“a“,b=“bendl;b+=fun(a);cout“a=“a“,b=“bendl;static int a=10;/静态全局变量int fun(int x)static int b=5;/静态局部变量b+=a;cout“a=“a“,b=“bendl;return b;本讲稿第七十二页,共九十页4.64.6 变量的生存期变量的生存期w程序执行结果a=10,b=15a=3,b=15a=10,b=25a=3,b=40本讲稿第七十三页,共九十页4.
32、74.7 递归函数递归函数w直接递归与间接递归直接递归与间接递归w递归调用的过程递归调用的过程w递归设计的要点递归设计的要点w举例:汉诺塔问题举例:汉诺塔问题w递归评价递归评价本讲稿第七十四页,共九十页4.74.7 递归函数递归函数w递归函数有两种:直接递归自己调用自己间接递归A调用B,B调用A本讲稿第七十五页,共九十页4.74.7 递归函数递归函数w直接递归与间接递归直接递归与间接递归直接递归直接递归间接递归间接递归A(int n)A(int n)A(n-1);B(n-1);B(int n)A(n-1);本讲稿第七十六页,共九十页4.74.7 递归函数递归函数w递归设计的要点递归设计的要点w
33、递归结束条件栈空间是有限的复杂性降低f(n)变为f(n-1)或者f(n-2)的问题,参数应逐渐逼近递归结束条件递归操作每次递归能完成一些操作(具有一些功能)本讲稿第七十七页,共九十页4.74.7 递归函数递归函数w递归调用的过程递归调用的过程(两个阶段)递推:递推:先将原问题不断分解成新的子问题,逐渐从未知向已知方向推测,最后到 达已知条件,即递归结束条件回归:回归:从已知条件出发,按“递推”的逆过程,逐一求值回归,最后到达递归开始处,结束回归,完成递归调用本讲稿第七十八页,共九十页4.74.7 递归函数递归函数w求n!的递归算法求值过程说明上述两个阶段3!=3*2!3!=3*2!=3*2=6
34、 2!=2*1!2!=2*1!=2*1=2 1!=1*0!1!=1*0!=1*1=10!=1递推递推递推递推递推递推回归回归回归回归回归回归本讲稿第七十九页,共九十页4.74.7 递归函数递归函数w求求n!n!的函数定义的函数定义long fact(int n)if(n=0)/递归结束条件 return 1;return n*fact(n-1);/递归调用语句 本讲稿第八十页,共九十页例:例:从键盘输入一个正整数,编程求出该数的阶乘从键盘输入一个正整数,编程求出该数的阶乘#includelong fact(int n);void main()int n;coutn;long fa=fact(n
35、);coutn“!=“faendl;long fact(int n)long p;if(n=0)p=1;else p=n*fact(n-1);return p;本讲稿第八十一页,共九十页4.74.7 递归函数递归函数w例:汉诺塔问题ABC本讲稿第八十二页,共九十页4.74.7 递归函数递归函数w例:汉诺塔问题ACB本讲稿第八十三页,共九十页4.74.7 递归函数递归函数 递归结束条件递归结束条件if(n=1)将盘子直接从A移到C 问题简化问题简化move(n,a,b,c)move(n-1,a,c,b)move(1,a,b,c)move(n-1,b,a,c)递归操作递归操作移动盘子移动盘子cou
36、ta“to”bendl;本讲稿第八十四页,共九十页4.74.7 递归函数递归函数w递归函数设计递归函数设计(汉诺塔问题)void move(int n,char a,char b,char c)if(n=1)couta“to”cendl;elsemove(n-1,a,c,b);move(1,a,b,c);move(n-1,b,a,c);递归结束条件递归结束条件递归操作递归操作问题简化问题简化本讲稿第八十五页,共九十页4.74.7 递归函数递归函数w递归评价好处:好处:程序简单可读性好坏处:坏处:效率低函数调用消耗时间和栈空间 本讲稿第八十六页,共九十页4.84.8 C+的库函数的库函数wC+编
37、译系统提供了几百个库函数w按其功能分类w每一类对应一个.h(头文件)w每个头文件中包含有该类每个库函数的原型本讲稿第八十七页,共九十页4.84.8 C+的库函数的库函数w例如:math.h指数、对数、绝对值等数学函数ctype.h判断字母、数字、大小写等string.h字符串处理函数conio.h屏幕处理函数graph.h图形处理函数.本讲稿第八十八页,共九十页4.84.8 C+的库函数的库函数w库函数的用法库函数的用法 了解你所使用的C+系统提供了那些库函数 要知道某个库函数的说明在哪个头文件中 调用一个库函数时,要搞清楚该函数的功能、参数和返回值要求本讲稿第八十九页,共九十页第四章 小结w函数应用函数应用 将什么定义为函数(有两个原则)-具有相对独立的功能-经常使用 能用简单的话描述出函数 如:初始化,求和,读取文件,交换两个数,打印等本讲稿第九十页,共九十页