《《函数和作用域》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《函数和作用域》PPT课件.ppt(74页珍藏版)》请在三一办公上搜索。
1、第四章 函数和作用域,函数的定义和说明函数的调用函数的参数内联函数函数重载函数的嵌套调用和递归调用作用域C+的系统函数,4.1 函数的定义和说明,一、函数的定义,(),函数返回值的类型,4.1 函数的定义和说明,一、函数的定义,(),函数的标识,4.1 函数的定义和说明,一、函数的定义,包括参数名和参数类型(无形参时,括号不可省),(),函数调用时的形式参数,4.1 函数的定义和说明,一、函数的定义,(),函数的具体实现,例:,int add(int x,int y)int z;z=x+y;return z;,void nothing(),二、函数的说明(声明),函数定义在后、调用在先,调用前
2、必须说明;函数定义在先、调用在后,可以不加说明;复杂调用中,常在程序头对所有被调用函数 一次性说明。,原型说明,例4.2,#include void fun1(),fun2(),fun3();void main()cout“It is in main.”endl;fun2();cout“It is back in main.”endl;void fun1()cout“It is in fun1.”endl;fun3();cout“It is back in fun1.”endl;void fun2()cout“It is in fun2.”endl;fun1();cout“It is back
3、 in fun2.”endl;void fun3()cout“It is in fun3.”endl;,4.2 函数的调用,(),void main()int a=3;int b=5;int c=add(a,b);/实参与形参个数相等,类型相同,实参,函数调用表达式的值是函数的返回值;函数调用表达式的类型是函数的类型;,函数调用通过一个表达式实现:,return;或 return;,函数的返回值通过返回语句实现,的值作为函数的返回值;的类型自动转换为函数类型;程序执行的控制权转向调用函数;,注:无返回值的函数用“void”说明类型!,一、函数的传值调用,1.传值调用,将实参值拷贝一个副本给对应
4、的形参;形参值的改变不影响实参!,变量的两种值:变量本身值和变量地址值;传值调用分为:传值调用和传址调用;,例4.3#include void swap1(int x,int y)int temp;temp=x;x=y;y=temp;/形参值交换 cout“x=”x“y=”yendl;void main()int a(5),b(9);swap1(a,b);cout“a=”a“b=”bendl;,a=5,b=9,x=9,y=5,将实参的地址值赋给对应的形参指针,使形参指针指向实参;通过改变形参所指向的变量值来影响实参!,2.传址调用,一、函数的传值调用,1.传值调用,例4.4#include v
5、oid swap2(int*x,int*y)int temp;temp=*x;*x=*y;*y=temp;/形参指针所指向的变量值交换 cout“x=”*x“y=”*yendl;void main()int a(5),b(9);swap2(,a=9,b=5,x=9,y=5,二、函数的引用调用/C+特色,将实参变量名赋给对应的形参引用,相当于在被调用函数中使用了实参的别名;通过改变引用来直接改变对应的实参值;引用调用比传址调用更直接。,引用是变量的别名对引用的操作就是对被引用的变量的操作,例4.5#include void swap3(int,a=9,b=5,x=9,y=5,形参:引用,实参:变
6、量,4.3 函数的参数,一、函数参数的求值顺序,C+没有规定函数调用时实参的求值顺序,各编译器自行规定;当实参表达式中带有副作用的运算符时,可能产生由于求值顺序不同而造成的二义性;,例4.6#include int add(int x,int y)return x+y;void main()int x(4),y(6);int z=add(+x,x+y);coutzendl;,二、设置函数参数的默认值,C+允许在函数说明或定义时为形参指定默认值;按从右至左的顺序设置参数的默认值;函数调用,实参与形参结合时:,若实参数目不足,则使用形参默认值;若给定实参值,则使用给定的实参值。,例4.7#incl
7、ude void fun(int a=1,int b=3,int c=5)couta=a,b=b,c=cendl;void main()fun();fun(7);fun(7,9);fun(7,9,11);,a=1,b=3,c=5,a=7,b=3,c=5,a=7,b=9,c=5,a=7,b=9,c=11,函数定义,例4.8#include int m(8);int add_int(int x,int y=7,int z=m);void main()int a(5),b(15),c(20);int s=add_int(a,b);coutsendl;int add_int(int x,int y,i
8、nt z)return x+y+z;,函数声明,函数定义,28,按自右至左的顺序设置参数的默认值;默认参数在函数声明中提供;既有函数声明又有函数定义时,定义中不允许默认参数;例4.8如果只有函数定义,默认参数才可以出现在函数定义中。例4.7,设置参数默认值应注意的问题:,三、使用数组作函数参数 1.形参和实参都用数组,49,实参,形参,2.形参和实参都用指针,49,实参,3.实参用数组名形参用引用,49,实参,4.4 内联函数,一、内联函数的引入,引入内联函数是为了解决函数调用时的效率问题;编译时,用内联函数的函数体替换内联函数的调用表达式(一般函数在运行时被调用);内联函数是以目标代码的增加
9、为代价来换取时间的节省。,二、内联函数的定义,inline(),#include inline int power(int x)return(x)*(x);void main()for(int i=1;i=10;i+)int p=power(i);couti“*”i“=”pendl;,例4.12,内联函数的定义必须出现在内联函数第一次被调用前;内联函数体内不允许用循环语句和开关语句;类结构中所有在类说明内部定义的函数都是内联函数。,使用内联函数时应注意:,4.5 函数重载,函数重载是指同一函数名对应多个函数实现;函数重载时,要求同名函数在参数个数上不同,或参数类型上不同;函数调用时,系统根据调
10、用函数的实参情况选择某个函数实现。,一、参数类型不同的函数重载,#include int add(int,int);double add(double,double);void main()coutadd(5,10)endl;coutadd(5.0,10.5)endl;int add(int x,int y)return x+y;double add(double a,double b)return a+b;,例4.13,二、参数个数不同的函数重载,#include int min(int a,int b)return ab?a:b;int min(int a,int b,int c)int
11、t=min(a,b);return min(t,c);void main()coutmin(5,4,9)endl;coutmin(-2,0)endl;,例4.14,4.6 函数的嵌套和递归调用,一、函数的嵌套调用,在调用一个函数的过程中,又调用另一个函数,例4.15,二、函数的递归调用,调用一个函数的过程中又直接或间接地调用该函数自身;,1.含义,2.特点,每次分解出的新问题是原问题的简化的子问题;最终分解出的新问题是一个已知解;程序简洁清晰,可读性强;,3.过程,回归:从已知条件出发,逐一求值回归,最终达递推开始处;,递推:原问题不断分解为新的子问题,最终达递归结束条件(已知);,例4.16
12、,#include long int fac(int n);void main()int n;coutn;long fa=fac(n);coutn!=faendl;long int fac(int n)long int p;if(n=0)p=1;else p=n*fac(n-1);return p;,例4.17,#include const int N=8;long fibo(int n);void main()long f=fibo(N);coutfendl;long fibo(int n)if(n=1)return 0;else if(n=2)return 1;else return fi
13、bo(n-1)+fibo(n-2);,4.7 作用域,一、标识符的作用域规则,标识符只能在其说明或定义的范围内可见,在该范围之外不可见!“可见”即可以进行存取或访问;标识符的说明和定义不完全一样;定义一个标识符总是在一定范围内定义的,作用范围有大有小;,二、作用域的种类,1.程序级(项目级最大),作用域:组成程序的所有文件;包括:外部变量和外部函数;,2.文件级,作用域:定义该标识符的文件内;包括:外部静态类变量和内部函数;,3.函数级,作用域:定义该标识符的函数体内;包括:函数形参、函数内的自动类变量、内部静态类变量、语句标号;,4.块级(最小),定义在分程序中、if语句、switch语句中
14、以及循环体中的自动类变量和内部静态类变量。,二、作用域的种类,三、重新定义标识符作用域,1.在标识符作用域的某个子范围内可以重新定义该标识符!,void fun()int a;/函数体内 float a;/分程序内,2.原定义的标识符在子范围内不可见,但仍存在(暂时被隐藏);,#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=b;couta b cendl;couta b cendl;couta b cendl;,5 7 10,5 8 8.8,8
15、8 8,8 8 8.8,8 7 10,例4.18,#include void main()int x(3);for(;x0;x-)int x(5);/重新定义变量x,作用域:块级coutx;coutendlxendl;,5 5 5,0,例4.19,四、局部变量和全局变量,1.局部变量,1)作用域:函数级和块级;,2)包括:自动类变量、内部静态变量和函数形参;,自动类变量auto,寄存器类变量register,内部静态类变量(static)定义在函数体内或分程序内,定义时有默认值;生存期长,可见性与存在性不一致(作用域外不可见但仍存在,回到作用域仍保留原值);,例4.20,#include vo
16、id other();void main()int a(3);register int b(5);static int c;couta=a,b=b,c=cendl;other();other();void other()int a(5);static int b(12);/内部静态类变量 a+10;b+=20;couta=a,b=bendl;,a=3,b=5,c=0,a=5,b=32,a=5,b=52,2.全局变量,1)作用域:程序级和文件级;,2)包括:外部变量和外部静态类变量;,外部变量的定义 定义在函数体外,定义时不加任何存储类说明;,外部变量的说明(声明)用说明符“extern”对外部
17、变量进行说明使用后定义的外部变量,在使用前必须说明;在一个文件中使用另一个文件定义的外部变量,必须说明;一个外部变量只能定义一次,但可以说明多次。,int add(int a,int b)int s=a+b;return s;void main()extern int x,y;/外部变量说明 coutadd(x,y)endl;int x(20),y(5);/外部变量定义,使用后定义的外部变量必须提前说明,例:,例4.21,#include void fun1(),fun2(),fun3();/函数说明int i(5);/外部变量:程序级void main()i=20;fun1();coutma
18、in():i=iendl;fun2();coutmain():i=iendl;fun3();coutmain():i=iendl;,文件:main.cpp,#includestatic int i;/外部静态变量:文件级void fun1()i=50;coutfun1():i(static)=iendl;,1)fun1():i(static)=50,文件:file1.cpp,3)fun2():i(auto)=15,4)fun2():i(extern)=20,文件:file2.cpp,例4.21,#include void fun1(),fun2(),fun3();int i(5);/外部变量:
19、程序级void main()i=20;fun1();coutmain():i=iendl;fun2();coutmain():i=iendl;fun3();coutmain():i=iendl;,2)main():i=20,文件:main.cpp,例4.21,#include void fun1(),fun2(),fun3();int i(5);/外部变量:程序级void main()i=20;fun1();coutmain():i=iendl;fun2();coutmain():i=iendl;fun3();coutmain():i=iendl;,文件:main.cpp,例4.21,#inc
20、lude void fun1(),fun2(),fun3();int i(5);/外部变量:程序级void main()i=20;fun1();coutmain():i=iendl;fun2();coutmain():i=iendl;fun3();coutmain():i=iendl;,5)main():i=20,文件:main.cpp,例4.21,#include void fun1(),fun2(),fun3();int i(5);/外部变量:程序级void main()i=20;fun1();coutmain():i=iendl;fun2();coutmain():i=iendl;fun
21、3();coutmain():i=iendl;,文件:main.cpp,6)fun3():i(extern)=30,7)fun3():i(auto)=10,文件:file2.cpp,例4.21,#include void fun1(),fun2(),fun3();int i(5);/外部变量:程序级void main()i=20;fun1();coutmain():i=iendl;fun2();coutmain():i=iendl;fun3();coutmain():i=iendl;,8)main():i=30,文件:main.cpp,例4.21,#include void fun1(),fu
22、n2(),fun3();int i(5);/外部变量:程序级void main()i=20;fun1();coutmain():i=iendl;fun2();coutmain():i=iendl;fun3();coutmain():i=iendl;,8)main():i=30,文件:main.cpp,五、内部函数和外部函数,1.内部函数,内部函数只在定义它的文件中可用!,static(),外部函数的作用域是整个程序!,4.8 C+的系统函数,一、C+系统函数概述,了解所用的C+系统提供哪些系统函数;知道某系统函数的说明放在哪个头文件中;调用一个函数时,要清楚其功能、参数和返回值。,二、字符串处
23、理函数,调用字符串处理函数时,要包含头文件string.h,1.字符串长度函数strlen(),int strlen(const char*s);,返回字符一个字符串的长度,空字符不计在内,3.字符串连接函数strcat(),char*strcat(char*s1,char*s2);,char*strncat(char*s1,char*s2,int n);,小 结,函数的定义和说明函数的调用(传值、传址、引用)嵌套调用和递归调用函数的参数(默认值)内联函数(inline)函数重载(参数个数、类型不同)作用域(4级)C+系统函数(字符串处理函数),实 验 一,调试例4.8、例4.13,掌握参数默
24、认值的设置和函数重载;编制程序,通过调用引用作参数的函数,实现两个字符串的交换。测试:char a50=“hello”;char b50=“how are you”;编写程序验证哥德巴赫猜想:任何一个充分大的偶数(=6)总可以表示成两个素数之和。,作 业 题,#includevoid f(int j);void main()for(int i(1);i=4;i+)f(i);void f(int j)static int a(10);/内部静态类变量 int b(1);/自动类变量 b+;couta+b+j=a+b+jendl;a+=10;,三(3),10+2+1=13,20+2+2=24,30
25、+2+3=35,40+2+4=46,三(6)传址调用,#includevoid fun(int,int,int*);void main()int x,y,z;fun(5,6,6,6,6,实参:地址,形参:指针,三(7)函数参数的默认值,#includeint add(int x,int y=8);void main()int a(5);coutsum1=add(a)endl;coutsum2=add(a,add(a)endl;coutsum3=add(a,add(a,add(a)endl;int add(int x,int y)return x+y;,sum1=13,sum2=18,sum3=
26、23,函数声明,三(10)引用作函数返回值,#includeint,10,s=5,4,3,10,1,0,引用,float,不是所有返回的引用都可以作为“左值”计算!返回不在作用域范围内的变量的引用,错误!,问题:引用作函数返回值,局部变量,float temp;float/此处temp“可见”,问题:引用作函数返回值,全局变量,三(12)函数重载,#includevoid ff(int),ff(double);void main()float a(88.18);ff(a);char b(a);ff(b);void ff(double x)coutff(double):xendl;void ff(int x)coutff(int):xendl;,ff(double):88.18,ff(int):97,