C++课件第3章:函数

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

第三章函数东南大学生物科学与医学工程学院夏小俊C++中的函数函数的概念与自定义函数函数的调用和声明变量的作用域与生存期函数的递归与嵌套函数的其它特性编译预处理3.1函数的概念与意义•任何c++程序由至少一个函数(function)组成,其中main函数是必不可少的。•函数除了是程序的基本组成部分之外,更重要的是可以完成特定的功能。•为了完成特定的功能,函数需要数据的输入(参数),并给出数据的结果(返回值)。•通过编写和调用函数可以简化程序逻辑,提高编码效率。子模块1子模块2子模块n功能模块1功能模块2功能模块n……………………软件项目C++程序C++函数搭积木系统函数与自定义函数•之前用过的sqrt()等函数并不需要我们去编写和思考实现。类似这样由系统提供的函数,我们称为系统函数或库函数。•使用系统函数可以大大提高我们的编程效率,但它并不能覆盖所有的需求。因此我们需要学习自己编写函数,也就是自定义函数。•编写自定义函数是结构化(模块化)程序设计的主要步骤。函数的参数和返回值•回忆之前使用函数的例子,如sqrt()。•使用该函数时,需要一个输入的值,并得到对应的输出,如y=sqrt(x)。•所以对于函数sqrt,需要一个类型为double的参数(输入),并提供一个类型为double的返回值(输出)。自定义函数的三部曲实现从参数得到返回值的过程分析函数的返回值(类型)分析函数的参数(个数、类型)第一个自定义函数max•函数功能:求两个整数当中较大的数。•函数逻辑:使用判断语句即可。•参数分析:需要两个参数,都是整数类型。•返回值分析:结果返回一个整数。自定义函数的语法格式•返回值类型函数名(函数参数列表)//函数头{//函数体return返回值;}•函数参数:数量为任意个,如果为0可以省略;•返回值说明:只能为0个或1个,用关键词return实现。如果没有返回值,返回类型用void表示。第一个自定义函数maxintmax(inta,intb)//每一个参数独立{intc=ab?a:b;returnc;//通过该语句返回结果}例:无参无返回值函数printvoidprint(void)//参数的void可省略{cout*********endl;cout*example*endl;cout*********endl;}//本函数仅仅实现打印的功能,无数据处理例:求最大公约数的函数gcd•函数功能:求两个整数的最大公约数。•函数逻辑:使用递推算法(欧几里得算法)或穷举法皆可。•参数分析:需要两个参数,都是整数类型。•返回值分析:结果返回一个整数。递推法实现函数gcdintgcd(inta,intb)//注意分析返回和参数类型{intc=a%b;//c是a除以b的余数while(c!=0)//欧几里得算法递推求解{a=b;b=c;c=a%b;}returnb;//返回最后的结果}穷举法实现函数gcdintgcd(inta,intb)//与上例相同{intc=ab?a:b;//二者中较小的数while(a%c!=0||b%c!=0)//尝试--c;returnc;//得到结果}函数定义小结•1、分析清楚函数所需的参数和能提供的返回值至关重要。•2、在函数实现过程中需要的辅助变量,不能作为参数来使用,只能定义在函数的内部。•3、遇到return语句之后函数自动结束,因此一般将return语句放在函数的最后。•4、思考和尝试将常用算法改造为函数实现,如判断某数是否为素数、完全数等,并体会这样做的好处。3.2函数的调用和声明自定义函数将返回值回传给主调函数运行自定义函数体主调函数将参数传递给自定义函数函数的调用过程主调函数将参数(实际参数)传递给自定义函数,并暂停主调函数的运行;自定义函数根据得到的参数(形式参数)值进行计算,并得出返回值结果;自定义函数将返回值回传给主调函数,结束自定义函数并继续主调函数的运行。函数的三种调用情况系统函数:包含所在的头文件自定义函数:定义之前,可直接调用自定义函数:定义之后,需补充声明函数的声明•从结构化程序设计的角度,通常是先调用后定义。而使用函数声明,符合由粗到精的思维方式,又满足了语法要求。•函数声明是将函数头添加分号而构成的语句,并且参数名可以省略。•部分函数声明示例intmax(inta,intb);voidprint(void);intgcd(int,int);//这里省略了参数名例:函数先定义后调用intmax(inta,intb){intc=ab?a:b;returnc;}intmain(){doublex=5.2,y=3.9;coutmax(5,3);//实参是常量coutmax(x,y);//实参是变量,且兼容coutmax(x+y,x-y);//实参是表达式且兼容return0;}intmax(inta,intb);//本声明必不可少!intmain(){intx=5,y=3;coutmax(5,3);//实参是常量coutmax(x,y);//实参是变量coutmax(x+y,x-y);//实参是表达式return0;}intmax(inta,intb){intc=ab?a:b;returnc;}例:函数先调用后定义函数的参数传递(传值调用)•两种参数:实际参数(实参)和形式参数(形参)。•传递过程是:先计算实参表达式的值,再将该值传递给对应的形参变量。•实参和形参的个数和排列顺序应一一对应,并且对应参数应类型匹配(赋值兼容)。•实参可以是常量、变量或表达式,形参只能是变量。实参与形参的单向传递•如前所述,在函数调用的过程中,实参将值传递给形参。•形参具备自己的存储空间,和实参的关系是单向传递关系。对形参的赋值不会影响对应的实参!•除了这种单向的传值调用之外,第5章还将介绍双向的传引用调用方式。例:用函数实现数据交换voidmyswap(int,int);//全局函数声明intmain(){inta,b;cinab;coutmain:a''bendl;myswap(a,b);//传值coutmain:a''bendl;}例:用函数实现数据交换voidmyswap(intx,inty){coutmyswap:x''yendl;intt=x;x=y;y=t;coutmyswap:x''yendl;}函数myswap运行结果分析输入两整数:35main:35//输出原始的结果myswap:35//实参将值传递给形参myswap:53//形参的交换成功main:35//实参的交换失败!函数返回值•return表达式;用来返回函数的结果。•如果该函数的返回类型不为void,那么函数的调用可以组成函数调用表达式参与运算。例:coutmax(a,b);max(max(a,b),c);•如果该函数的返回类型为void,那么函数的调用只能加上分号成为函数语句。例:print();return语句的操作本质•当函数中运行到return语句的时候,将return后面表达式的值传给指定类型的临时变量;•临时变量仅在函数表达式内有效,因此函数表达式一般不为左值,如max(a,b)=2是非法的;•如果return后面表达式的类型和函数定义的返回类型不一致,以定义类型为准进行转换。例:三角形面积求解函数floatTriangleArea(floata,floatb,floatc){if((a+b=c)||(a+c=b)||(b+c=a))return-1;floats=(a+b+c)/2;returnsqrt(s*(s-a)*(s-b)*(s-c));}intmain(){floata,b,c,area;cout输入三角形三边a,b,c:endl;cinabc;area=TriangleArea(a,b,c);if(area==-1)cout不能构成三角形!endl;elsecout面积为:areaendl;return0;}3.3变量的作用域和生存期•变量除了具备类型、名字和值之外,还有空间和时间上的特性,也被称为变量的作用域和生存期。•根据作用域和生存期的不同,可对变量进行不同形式的分类。C++的内存分布代码区:存放程序代码指令堆区:存储动态数据栈区:存放局部变量全局数据区:存放全局和静态变量变量的存储机制(*)•代码区(Codearea):存放程序代码,即程序中各个函数的代码块;•全局数据区(Dataarea):存放全局数据和静态数据;分配该区时内存全部清零,变量的所有字节自动初始化为零。•栈区(Stackarea):存放局部变量,如函数中的变量等;分配栈区时不处理内存,即变量取随机值。•堆区,自由存储区(Freestorearea):存放与指针相关的动态数据。变量的作用域与生存期•C++中的变量除了有数据类型的区别之外,还具备作用域(空间)和生存期(时间)的属性。•根据作用域的不同,将变量分为全局变量和局部变量。•根据生存期的不同,将变量分为静态变量和动态变量。全局变量•如果一个变量定义的位置不在任何函数(复合语句)内,则该变量成为全局变量。•全局变量的作用域:由定义处开始,到所在文件尾部结束,因此也称为文件作用域。•一般情况下,将全局文件定义在文件的开头部分,则所有函数中都可以对全局变量进行读写。例:全局变量的使用intn=100;voidfunc(){n*=2;}intmain(){n*=2;coutnendl;//输出200func();coutnendl;//输出400return0;}全局变量的说明•全局变量可以被多个函数同时使用,因此可以用来做数据交换和共享的用途(例如:用来统计递归函数的运行次数)。•全局变量的使用应尽量谨慎,过多地使用容易导致逻辑和流程的混乱。•全局变量的存储地点在内存的全局数据区,如不赋初始值则自动初始化为0。局部变量•之前所有的变量都是局部变量,其特点是变量定义在某个特定的函数内。•与函数的情况类似,如果一个变量定义在某复合语句(块)内,则该变量成为此复合语句的局部变量。•局部变量的作用域:从变量定义开始,到所在的函数(复合语句)的尾部结束,也称为块域。•局部变量的存储地点在内存的栈区。作用域的覆盖问题•问:属于不同函数的局部变量允许重名吗?全局变量和局部变量可以重名吗?不同层次的局部变量可以重名吗?•答:都允许。在作用域覆盖的区域内,遵循“局部优先”的规则。•另外,如果局部变量覆盖了全局变量,可以使用域作用符::调用同名全局变量。例:变量的作用域覆盖intn=100;intmain(){inti=200,j=300;coutn'\t'i'\t'jendl;{inti=500,j=600,n;n=i+j;coutn'\t'i'\t'jendl;cout::nendl;//输出全局变量n}n=i+j;//修改全局变量coutn'\t'i'\t'jendl;return0;}作用域的总结•根据变量定义时的位置不同,将其分为全局变量和局部变量。•全局变量可以被所有函数(块)访问,而局部变量只能在该函数(块)内被访问。•全局变量和局部变量可以重名,并遵循局部优先的规则。•还有一种作用域:局部声明作用域,其作用范围仅限声明语句内,因此可省略其参数名。变量的生存期•动态变量:当程序运行至变量所在的函数(块)的时候,系统对其进行空间分配;当所在的函数(块)运行结束时,系统收回其存储空间。之前使用的局部变量一般就属于动态变量。•静态变量:当程序开始运行的时候,变量即被创建,并一直生存至程序的结束。之前的全局变量即为静态变量。另可改造普通局部变量的属性,使其成为静态局部变量。•不同生存期的变量,用存储类型的不同来体现。变量的存储类型•变量定义的完整方式存储类型数据类型变量名=初始值;

1 / 89
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功