资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,C+,语言程序设计(第,4,版),郑莉,清华大学,计算机程序设计基础,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,C+,语言程序设计(第,4,版),郑莉,清华大学,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,C+,语言程序设计(第,4,版),郑莉,清华大学,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,C+,语言程序设计(第,4,版),郑莉,清华大学,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,C+,语言程序设计(第,4,版),郑莉,清华大学,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,C+,语言程序设计(第,4,版),郑莉,清华大学,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,C+,语言程序设计(第,4,版),郑莉,清华大学,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,C+,语言程序设计(第,4,版),郑莉,清华大学,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,C+,语言程序设计(第,4,版),郑莉,清华大学,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,C+,语言程序设计(第,4,版),郑莉,清华大学,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,C+,语言程序设计(第,4,版),郑莉,清华大学,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,第,六讲,函数(,2,),清华大学 郑 莉,教材:,C+,语言程序设计,(第,4,版)第,3,章,3.23.7,目录,6.1,内联函数,6.2,带缺省形参值的函数,6.3,函数重载,6.4,使用,C+,系统函数,6.5,深度探索,6.6,小结,2,6.1 内联函数,声明时使用关键字,inline,。,编译时在调用处用函数体进行替换,节省了参数传递、控制转移等开销。,注意:,内联函数体内不能有,循环语句,和,switch,语句。,内联函数的声明必须出现在内联函数第一次被调用之前。,对内联函数不能进行异常接口声明。,3,例6-1(教材例3-14)内联函数应用举例,#include,using namespace std;,const double PI=3.14159265358979;,inline double calArea(double radius),return PI*radius*radius;,int main(),double r=3.0;,double area=calArea(r);,cout area endl;,return 0;,4,6.1,内联函数,6.2 带缺省形参值的函数,函数在声明时可以预先给出缺省的形参值,调用时如给出实参,则采用实参值,否则采用预先给出的缺省形参值。,例如:,int add(int x=5,int y=6),return x+y;,int main(),add(10,20);/10+20,add(10);/10+6,add();/5+6,5,例6-2(教材例3-15)计算长方体的体积,子函数,getVolume,是计算体积的函数,有三个形参:,length,(长)、,width,(宽)、,height,(高),其中,width,和,height,带有缺省值。,主函数中以不同形式调用,getVolume,函数,分析程序的运行结果。,8,6.2,带缺省形参值的函数,#include,#include,using namespace std;,int getVolume(int length,int width=2,int height=3);,int main(),const int X=10,Y=12,Z=15;,cout Some box data is ;,cout getVolume(X,Y,Z)endl;,cout Some box data is ;,cout getVolume(X,Y)endl;,cout Some box data is ;,cout getVolume(X)endl;,return 0;,int getVolume(int length,int width/*=2*/,int height/*=3*/),cout setw(5)length setw(5)width setw(5)height t;,return length*width*height;,9,6.2,带缺省形参值的函数,例6-2(续),6.3 函数重载,C+,允许功能相近的函数在相同的作用域内以相同函数名声明,从而形成重载。方便使用,便于记忆。,例:,10,形参类型不同,int add(,int,x,int,y);,float add(,float,x,float,y);,形参个数不同,int add(int x,int y);,int add(int x,int y,int z,);,注意事项,11,6.3,函数重载,不要将不同功能的函数声明为重载函数,以免出现调用结果的误解、混淆。这样不好:,int add(int,x,int,y,);,int add(int,a,int,b,);,编译器不以,形参名,来区分,int,add(int x,int y);,void,add(int x,int y);,编译器不以,返回值,来区分,int,add,(int x,int y),return x,+,y;,float,add,(float x,float y),return x,-,y;,重载函数的形参必须不同,:,个数,不同或,类型,不同。,编译程序将根据实参和形参的类型及个数的最佳匹配来选择调用哪一个函数。,例6-3(教材例3-16)重载函数应用举例,编写两个名为,sumOfSquare,的重载函数,分别求两整数的平方和及两实数的平方和。,12,6.3,函数重载,#include,using namespace std;,int sumOfSquare(int a,int b),return a*a+b*b;,double sumOfSquare(double a,double b),return a*a+b*b;,int main(),int m,n;,cout m n;,cout Their sum of square:sumOfSquare(m,n)endl;,double x,y;,cout x y;,cout Their sum of square:sumOfSquare(x,y)endl;,return 0;,13,6.3,函数重载,例,6-3,(续),运行结果:,Enter two integer:3 5,Their sum of square:34,Enter two real number:2.3 5.8,Their sum of square:38.93,例,6-3,(续),6.3,函数重载,6.4 使用C+系统函数,C+,的系统库中提供了几百个函数可供程序员使用。,例如:求平方根函数(,sprt,)、求绝对值函数(,abs,)等。,使用系统函数时要包含相应的头文件。,例如:,cmath,或,math.h,15,例6-4(教材例3-17)系统函数应用举例,题目:,从键盘输入一个角度值,求出该角度的正弦值、余弦值和正切值。,分析:,系统函数中提供了求正弦值、余弦值和正切值的函数:,sin(),、,cos(),、,tan(),,函数的说明在头文件,cmath,中。,16,6.4,使用,C+,系统函数,#include,#include,using namespace std;,const double PI=3.14159265358979;,int main(),double angle;,cout angle;/,输入角度值,double radian=angle*PI/180;/,转化为弧度值,cout sin(angle )=sin(radian)endl;,cout cos(angle )=cos(radian)endl;,cout tan(angle )=tan(radian)Visual Studio -Visual C+-Reference -Libraries Reference,-Run-Time Library -Run-Time Routines by Category,19,6.4,使用,C+,系统函数,6.5.1运行栈与函数调用的执行 形参和局部变量的存储,为什么不能为形参和局部变量分配固定地址?,他们仅在函数调用时生效,函数返回后即失效,分配固定地址造成空间浪费,更重要的是,发生递归调用时,多次调用间的形参和局部变量应彼此独立,需要栈式存储,20,6.5,深度探索,栈,栈是一种容纳数据的容器,数据只能从栈的一端存入(压入栈),数据只能从栈的同一端取出(弹出栈),21,6.5,深度探索,6.5.1,运行栈与函数调用的执行,a,n,a,2,a,1,压入栈,弹出栈,栈顶,栈底,运行栈,运行栈是一段区域的内存空间,运行栈分为一个一个栈帧,每个栈帧对应一次函数调用,栈帧中包括:,本次函数调用的形参值,控制信息,局部变量值,一些临时数据,函数调用时,会一个栈帧被压入运行栈,返回时,会有一个栈帧被弹出,22,6.5,深度探索,6.5.1,运行栈与函数调用的执行,运行栈示意图,unsigned,fac,(unsigned n),unsigned f;,if(n=0),f=1;,else,f=,fac,(n-1)*n;,return f;,int main(),unsigned n;,cin n;,unsigned y=,fac,(n);,23,6.5,深度探索,6.5.1,运行栈与函数调用的执行,n:0,f:?,n:1,y:?,n:1,f:1,main(),fac(1),fac(0),栈顶,函数调用的执行过程,栈指针,esp,:指向运行栈栈顶,帧指针,ebp,:定位形参和局部变量,传递参数:调用前把实参压入堆栈,函数调用时的几步关键操作,call,指令:将下一条指令地址(返回地址)压入运行栈,转到函数入口地址,被调函数入口处:将当前,ebp,压入运行栈,用,ebp,保存,esp,,调整,esp,为局部变量留出空间,被调函数出口处:用,ebp,恢复,esp,,从运行栈中弹出,ebp,原值,ret,指令:将返回地址从运行栈弹出,转到返回地址,24,6.5,深度探索,6.5.1,运行栈与函数调用的执行,运行栈的数据分布,unsigned,fac,(unsigned n),unsigned f;,if(n=0),f=1;,else,f=,fac,(n-1)*n;,return f;,25,6.5,深度探索,6.5.1,运行栈与函数调用的执行,局部变量,f,ebp,原值,返回地址,参数,n,调用,fib(n-1),的参数,n,esp,ebp,fib,的栈帧,形参和局部变量定位:,ebp 8,:形参,n,ebp+4,:局部变量,f,6.5.2 函数声明与类型安全,以错误方式调用函数的危险性,函数的原型信息(参数个数和类型、返回值类型)在编译后即不存在;,如果不要求声明函数,以错误的方式(错误的参数数量或类型)调用函数,会产生不可预期的结果,但很多情况下不会给出错误提示。,函数原型是主调函数与被调函数间的协议,运行结果错误,vs,编译错误,一个错误,与其被淹没在运行中,不如暴露在编译时。,26,6.5,深度探索,C语言的反例,27,6.5,深度探索,6.5.2,函数声明与类型安全,C,语言允许,只声明函数名和返回类型,而不声明参数类型,不声明函数,直接调用,后果:隐蔽错误,如果给出,add(),的完整声明,则会自动进行类型转换。,声明带来了类型安全,double add();,int main(),double s=add(1,2);,.,return 0;,double add(double a,double b),return a+b;,不完整的函数声明,错误的调用,压入,运行栈的是整数!,6.6 小结,主要内容,内联函数、带默认形参值的函数、函数重载、,C+,系统函数,达到的目标,学会将一段功能相对独立的程序写成一个函数,为下一讲学习类和对象打好必要的基础。,28,
展开阅读全文