(中职)Visual C++程序设计基础(中职)Flash 8.0基础第5章 函数与预处理ppt课件.ppt
(中职)Visual C+程序设计基础(中职)Flash 8.0基础第5章 函数与预处理ppt课件第第5章章 函数与预处理函数与预处理5.1 函数的定义函数的定义5.2 函数的调用函数的调用5.3 指针与函数指针与函数5.4 函数的嵌套调用函数的嵌套调用5.5 函数的递归调用函数的递归调用5.6 内联函数和重载函数内联函数和重载函数5.7 默认参数的函数默认参数的函数5.8 作用域与生命期作用域与生命期5.9 编译预处理编译预处理5.1 函数的定义函数的定义 在在C+中,程序可由一个主函数中,程序可由一个主函数main和若干个函数构和若干个函数构成。主函数是程序执行的起始点,而且程序中必须有且只成。主函数是程序执行的起始点,而且程序中必须有且只能有一个主函数。程序的执行从能有一个主函数。程序的执行从main函数开始,在函数开始,在main的执行过程中可以调用其它函数,这些函数执行完毕后再的执行过程中可以调用其它函数,这些函数执行完毕后再返回到返回到main中继续执行,直到中继续执行,直到main执行结束,则整个程执行结束,则整个程序的执行结束。序的执行结束。在在C+中的一个调用关系中,调用其它函数的函数称中的一个调用关系中,调用其它函数的函数称为主调函数,被其它函数调用的函数称为被调函数。一个为主调函数,被其它函数调用的函数称为被调函数。一个函数有可能既是主调函数也是被调函数,但是,主函数函数有可能既是主调函数也是被调函数,但是,主函数main只能是主调函数,主函数可以调用其它函数,但是只能是主调函数,主函数可以调用其它函数,但是不能被其它任何函数调用。不能被其它任何函数调用。5.1.1 函数概念的引入函数概念的引入#include void main()static int a20=8,12,19,23,33,39,42,55,62,69,76,85;int n=12,i,x;coutThe numbers are:n;for(i=0;in;i+)coutait;cout*n;coutx;for(i=n-1;i=0;i-)if(aix)ai+1=ai;else break;ai+1=x;n+;coutThe numbers are:n;for(i=0;in;i+)coutait;cout*n;l一段程序被执行了多次一段程序被执行了多次l优化程序结构优化程序结构l通用:函数库通用:函数库函数的引入函数的引入#include void main()static int a20=8,12,19,23,33,39,42,55,62,69,76,85;int n=12,i,x;arrayprint(a,n);coutx;for(i=n-1;i=0;i-)if(aix)ai+1=ai;else break;ai+1=x;n+;arrayprint(a,n);void arrayprint(int a,int n)coutThe numbers are:n;for(i=0;in;i+)coutait;coutab;s=add(a,b);coutsendl;函数说明函数说明数据类型数据类型数据类型数据类型 函数名函数名函数名函数名(形参列表形参列表形参列表形参列表)double area(double x,double y,double z)double s;if(x+yz|x+zy|y+zab;s=add(a,b);coutsendl;double area(double x,y,z)double s;if(x+yz|x+zy|y+zx)return 0;s=(x+y+z)/2;s=sqrt(s*(s-x)*(s-y)*(s-z);return s;清楚了吗?清楚了吗?函数体函数体例例1 无参函数无参函数display_sum,用来计,用来计算两个数之和。算两个数之和。#include void display_sum()int x,y,sum;cout Enter a and b:x y;sum=x+y;cout x+y=sum endl;void main()display_sum();由由花花括括号号所所括括起起的的语语句句序序列列,是是完完成成函函数数功功能能所所要要执执行行的的具具体体操操作作。当当函函数数执执行行结结束束需需要要返返回回一一个个值值时时,在这个函数体中还必须有一个在这个函数体中还必须有一个return语句。语句。例例2 有有参参函函数数sum,用用于于求求两个数之和。两个数之和。int sum(int x,int y)int temp;temp=x+y;return temp;void main()int s=sum(10,5);cout”sum=”s;N!三角形面积double power(int n)int i;double l=1;for(i=1;i=n;i+)l*=i;return l;double area(double x,double y,double z)double s;if(x+yz|x+zy|y+zx)return 0;s=(x+y+z)/2;s=sqrt(s*(s-x)*(s-y)*(s-z);return s;5.1.3 return语句语句_语句格式:语句格式:return;/无值无值voidreturn 表达式;表达式;/有值有值return(表达式表达式);/有值有值_函函数数体体中中的的流流程程控控制制语语句句。先先计计算算表表达达式式的的值值,然然后后从从被被调调函函数数返返回回到到主主调调函函数数,表表达达式式的的值值作作为为函函数数的的返返回回值值。(注注意意:只只能能返回一个值返回一个值)_函函数数值值的的类类型型:以以函函数数定定义义的的类类型型为为准准,若若不不同同,需需将将return语语句表达式的值转换类型。句表达式的值转换类型。_无无返返回回值值void时时,可可无无return语语句,执行到函数体句,执行到函数体时返回。时返回。例例 有有参参函函数数sum,用用于于求求两个数之和。两个数之和。int sum(int x,int y)int temp;temp=x+y;return temp;void main()int s=sum(10,5);cout”sum=”s;return语句语句_在在一一个个函函数数中中可可有有多多个个return语语句句,但但每每次次被被调调用用只只能能执执行行一一个个return语语句句。例例,判判断断素素数数(或求三角形面积)(或求三角形面积)#includevoid main()int i;for(i=2;i100;i+)if(sushu(i)coutti;#includeint sushu(int n)int k,i;k=sqrt(double)n);for(i=2;i=k;i+)if(!(n%i)return 0;return 1;5.1.4 函数声明函数声明_函数函数原型原型的形式:的形式:数据类型数据类型 被调函数的函数名被调函数的函数名(形参类型说明形参类型说明);例:例:double area(double,double,double);_参数类型说明列表是用逗号隔开的的参数类型说明,其参数个数参数类型说明列表是用逗号隔开的的参数类型说明,其参数个数和类型必须和函数定义中的参数个数和类型一致。也可以给出参和类型必须和函数定义中的参数个数和类型一致。也可以给出参数名,但对编译器没有什么意义。数名,但对编译器没有什么意义。_函数原型用来说明一个函数的返回值类型、参数的个数和类型。函数原型用来说明一个函数的返回值类型、参数的个数和类型。使编译器检查该函数被调用的正确与否。使编译器检查该函数被调用的正确与否。s=area(a,b,c);_函数必须先说明后调用。函数必须先说明后调用。_调用库函数时,一般在文件的开头用调用库函数时,一般在文件的开头用#include 命令将包含该函命令将包含该函数数原型原型的头文件加入到程序中的头文件加入到程序中。_调调用用户自定义函数,用用户自定义函数,当对一个函数的调用出现在该函数定义之当对一个函数的调用出现在该函数定义之前时,必须先对函数进行原型声明。即前时,必须先对函数进行原型声明。即当被调函数的定义写在主当被调函数的定义写在主调函数后面时才需声明调函数后面时才需声明。example1:求三角形面积#include#include double area(double,double,double);/*需要需要声明声明*/void main()double a,b,c,s;coutabc;s=area(a,b,c);cout“area=“s“n”;double area(double x,double y,double z)double s;if(x+yz|x+zy|y+zx)return 0;s=(x+y+z)/2;return sqrt(s*(s-x)*(s-y)*(s-z);#include#include double area(double x,double y,double z)double s;if(x+yz|x+zy|y+zx)return 0;s=(x+y+z)/2;return sqrt(s*(s-x)*(s-y)*(s-z);void main()/*不需声明不需声明*/double a,b,c,s;coutabc;s=area(a,b,c);cout“area=“s“n”;_实实参参表表可可包包含含多多个个参参数数,用用逗逗号号分分开开;可可为为常常量量、变变量量、函函数调用、表达式(先求值,再将值传递给形参)。数调用、表达式(先求值,再将值传递给形参)。_要求实参的类型和个数要与形参一致。要求实参的类型和个数要与形参一致。_可以没有参数,但圆括号一定要有,不能省略。可以没有参数,但圆括号一定要有,不能省略。_函数调用一般用来构成表达式。函数调用一般用来构成表达式。5.2.1 函数的调用形式函数的调用形式 函数调用是用一个表达式表示,其形式为:函数调用是用一个表达式表示,其形式为:函数名函数名函数名函数名(实参列表实参列表实参列表实参列表)5.2 函数的调用函数的调用t=sqrt(t*(t-a)*(t-b)*(t-c);s=area(a,b,c);s=sum(5,7);例例5.2.2 函数调用过函数调用过程程1 1在主调函数中通过函数调用转到被调函数从而开始执行被在主调函数中通过函数调用转到被调函数从而开始执行被在主调函数中通过函数调用转到被调函数从而开始执行被在主调函数中通过函数调用转到被调函数从而开始执行被调函数。调函数。调函数。调函数。2 2执行被调函数时,遇到执行被调函数时,遇到执行被调函数时,遇到执行被调函数时,遇到returnreturn语句或函数体的右大括号语句或函数体的右大括号语句或函数体的右大括号语句或函数体的右大括号,则返回主调函数继续执行下面的语句。,则返回主调函数继续执行下面的语句。,则返回主调函数继续执行下面的语句。,则返回主调函数继续执行下面的语句。3 3函数间相互独立:各函数中的变量互不相关,可同名。函数间相互独立:各函数中的变量互不相关,可同名。函数间相互独立:各函数中的变量互不相关,可同名。函数间相互独立:各函数中的变量互不相关,可同名。主调函数主调函数被调函数被调函数float area(x,y,z)return smain()s=area(a,b,c);实实 参参形形 参参 参数传递?参数传递?参数传递?参数传递?返回值返回值返回值返回值 函数调用时,主调函数与被调函数之间要进行数据传递,函数调用时,主调函数与被调函数之间要进行数据传递,参数是函数之间交换数据的通道。函数之间的参数传递是按照参数是函数之间交换数据的通道。函数之间的参数传递是按照参数书写的先后次序(与参数名无关),由实参向形参的单向参数书写的先后次序(与参数名无关),由实参向形参的单向传递,因此要求实参与形参的类型、个数等必须一致。传递,因此要求实参与形参的类型、个数等必须一致。主调函数中实参可为任意表达式,但是在进行函数调用时主调函数中实参可为任意表达式,但是在进行函数调用时要具有确定的值。对于形参来说,在函数未被调用时,形参没要具有确定的值。对于形参来说,在函数未被调用时,形参没有实际意义,不占用存储空间;当函数被调用时,此时系统为有实际意义,不占用存储空间;当函数被调用时,此时系统为形参分配存储单元,实参和形参之间进行数据传递;当函数调形参分配存储单元,实参和形参之间进行数据传递;当函数调用结束时,系统释放形参所占的存储单元。用结束时,系统释放形参所占的存储单元。C+中有两种不同的参数传递机制,一种称为传值调用(值中有两种不同的参数传递机制,一种称为传值调用(值调用),另一种称为引用调用。调用),另一种称为引用调用。5.2.3 参数传递机制参数传递机制 变量的值传递变量的值传递 参数使用变量的值传递方式时,形参为变量名,实参可为常量、参数使用变量的值传递方式时,形参为变量名,实参可为常量、变量或表达式。调用函数时,首先计算实参的值,然后系统为形参分变量或表达式。调用函数时,首先计算实参的值,然后系统为形参分配存储单元,并将实参的值按书写顺序赋给对应的形参,即对形参进配存储单元,并将实参的值按书写顺序赋给对应的形参,即对形参进行初始化。被调函数中的操作是在形参的存储单元中进行的,形参的行初始化。被调函数中的操作是在形参的存储单元中进行的,形参的值可以改变,但不会影响到主调函数中实参的值。所以变量的值传递值可以改变,但不会影响到主调函数中实参的值。所以变量的值传递的特点是形参值的改变不会影响实参的值。的特点是形参值的改变不会影响实参的值。1.传值调用:传值调用:变量的地址传递变量的地址传递使用地址传递方式时,主调函数的实参为变量的地址值,被调函数的使用地址传递方式时,主调函数的实参为变量的地址值,被调函数的形参为指针变量。函数调用时,系统将实参(地址值)赋给对应的形形参为指针变量。函数调用时,系统将实参(地址值)赋给对应的形参指针变量,则形参和实参指向同一存储单元,此时在被调函数中,参指针变量,则形参和实参指向同一存储单元,此时在被调函数中,通过改变形参指针所指向的变量值,从而实现对主调函数中变量值的通过改变形参指针所指向的变量值,从而实现对主调函数中变量值的修改。修改。因此,地址传递的实现机制就是使实参和形参指向相同的存储单元,因此,地址传递的实现机制就是使实参和形参指向相同的存储单元,从而可以达到被调函数修改主调函数中多个变量值的目的。从而可以达到被调函数修改主调函数中多个变量值的目的。#include void swap(int x,int y)int t=x;x=y;y=t;void main()int a=3;int b=4;couta=ab=bendl;cout-swap-endl;swap(a,b);/调用调用swap函数函数 couta=ab=bendl;运行结果:运行结果:a=3 b=4 -swap-a=3 b=4例:编写例:编写swap函数实现两个变量值的交换函数实现两个变量值的交换 变量的值传递的例子变量的值传递的例子void swap(int*x,int*y)/函数定义,形参为指针变量函数定义,形参为指针变量 int t=*x;*x=*y;/交换指针变量交换指针变量x、y所指向的变量的值所指向的变量的值*y=t;#include void swap(int*x,int*y);/函数原型说明函数原型说明void main()int a=3,b=4;couta=ab=bendl;cout-swap-endl;swap(&a,&b);/函数调用语句,实参为变量的地址函数调用语句,实参为变量的地址couta=ab=bendl;运行结果:运行结果:a=3 b=4 -swap-a=4 b=3例:修改前例,使用变量的地址传递方式实现两个变量值的交换例:修改前例,使用变量的地址传递方式实现两个变量值的交换 变量的地址变量的地址传递的例子传递的例子 在在C+中中,也也可可以以通通过过在在函函数数中中使使用用引引用用参参数数来来解解决决上上面面的的问问题题。要要把把形形式式参参数数声声明明为为引引用用类类型型,只只需需在在参参数数名名字字前前加加上上引引用用运运算算符符&即即可可。简简单单地地说说,引引用用是是给给一一个个已已知知变变量量起起别别名名,它它不不占占用用任任何何存存储储单单元元,对对引引用用的的操操作作也也就就是是对对被被它它引引用用的的变变量量的的操操作作,它它们们代代表表的的是是同同一一存存储储单单元元。因因此此当当形形参参为为引引用用类类型型时时,实实参参用用变变量量名名,此此时时在在被被调调函函数数中中对对引引用用的的任任何何操操作作,实实质质上上都都是是对对实实参参的的操操作作,实实参参的的值值将将随随函函数数体体内内形形参参的的改改变变而改变。通常,引用主要是用来作函数的形参和函数的返回值。而改变。通常,引用主要是用来作函数的形参和函数的返回值。2.引用调用引用调用5.2.3 参数传递机制参数传递机制#includevoid swap(int&x,int&y)/形参为引用类型形参为引用类型 int t=x;x=y;y=t;void main()int a=3;int b=4;couta=ab=bendl;cout-swap-endl;swap(a,b);/函数调用语句,实参为变量名函数调用语句,实参为变量名 couta=ab=bendl;例:使用引用调用的方法实现两个变量的值的交换例:使用引用调用的方法实现两个变量的值的交换例:使用引用调用的方法实现两个变量的值的交换例:使用引用调用的方法实现两个变量的值的交换5.2.3 参数传递机制参数传递机制运行结果:运行结果:a=3 b=4-swap-a=4 b=35.3 指针与函数指针与函数#includeint fun(int*);void main()int a=8,b;b=fun1(&a);couta=“a“b=“b;int fun1(int*p)int x=4;*p+=x;coutx*p“n”;return*p*x;8abpa=12b=484x48125.3.1 指针变量作为函数参数指针变量作为函数参数4 12#includeint fun(int*);void main()int a=8,b;b=fun1(&a);couta=“a“b=“b;int fun1(int*p)int x=4;*p+=x;coutx*p“n”;return*p*x;#includeint fun(int);void main()int a=8,b;b=fun1(a);couta=“a“b=“b;int fun1(int p)int x=4;p+=x;coutxp“n”;return p*x;a=12b=484 12传变量的值和地址的区别a=8b=484 12swap(int*x,int*y)int t;t=*x;*x=*y;*y=t;#includevoid main()int a,b;a=5;b=9;swap(&a,&b);cout“a=“a“b=“b;swap(int x,int y)int t;t=x;x=y;y=t;#includevoid main()int a,b;a=5;b=9;swap(a,b);cout“a=“a“b=“b;程序程序 1程序程序 2 例:编写函数实现两数的互换例:编写函数实现两数的互换主调函数主调函数被调函数被调函数实实 参参形形 参参结果有何不同?结果有何不同?主调函数主调函数被调函数被调函数includeint swap(int,int);void main()int a,b;a=5;b=9;swap(a,b);cout“a=“a“b=“b;swap(int x,int y)int t;t=x;x=y;y=t;55ab实实 参参形形 参参99xyab程序程序 1xy95主调函数主调函数被调函数被调函数&a实实 参参形形 参参&b*x*yabswap(int*x,int*y)int t;t=*x;*x=*y;*y=t;#includeint swap(int*,int*);void main()int a,b;a=5;b=9;swap(&a,&b);cout“a=”a“b=“b;5ab9程序程序 2xy&b&a95指针变量作为函数参数指针变量作为函数参数_指针作为函数的参数时,是以变量的地址作为实参指针作为函数的参数时,是以变量的地址作为实参调用一个函数,即作为参数传递的不是数据本身,调用一个函数,即作为参数传递的不是数据本身,而是数据的地址。因此,与之相应的被调用函数中而是数据的地址。因此,与之相应的被调用函数中的形参应为指针变量,并且其数据类型必须与被传的形参应为指针变量,并且其数据类型必须与被传递参数的数据类型保持一致。递参数的数据类型保持一致。_在主调函数中,要以变量的存储地址作为实参来调在主调函数中,要以变量的存储地址作为实参来调用另一个函数。用另一个函数。_被调用函数的形参必须是可以接受地址值的指针变被调用函数的形参必须是可以接受地址值的指针变量,而它的数据类型应与被传送的数据类型保持一量,而它的数据类型应与被传送的数据类型保持一致。致。_在程序设计中,经常需要把数组中的数据传递到函数中进行处在程序设计中,经常需要把数组中的数据传递到函数中进行处理。此时必须将整个数组的各个元素的值传递给函数。如果使用理。此时必须将整个数组的各个元素的值传递给函数。如果使用变量的值传递的方案,则需要将所有的数组元素作为实参进行传变量的值传递的方案,则需要将所有的数组元素作为实参进行传递,这样不仅内存开销很大,而且在某些情况下并不能实现程序递,这样不仅内存开销很大,而且在某些情况下并不能实现程序所要求的功能,所以通常不采用这种传递方式,而是采用地址传所要求的功能,所以通常不采用这种传递方式,而是采用地址传递方式。递方式。_指针变量可以作为函数的参数,而数组名本身就代表着数组所指针变量可以作为函数的参数,而数组名本身就代表着数组所在存储空间的首地址,因此可以将数组名作为参数。当实参为数在存储空间的首地址,因此可以将数组名作为参数。当实参为数组名时,形参可以是指针变量,也可以是数组名。此时,实参和组名时,形参可以是指针变量,也可以是数组名。此时,实参和形参之间的数据传递方式是数组首地址值的传递方式。函数的调形参之间的数据传递方式是数组首地址值的传递方式。函数的调用过程为:数组名(即数组首地址)作为实参传递给形参(数组用过程为:数组名(即数组首地址)作为实参传递给形参(数组名或指针变量),这样实参和形参指向的是同一个存储空间,因名或指针变量),这样实参和形参指向的是同一个存储空间,因此在被调函数中对形参数组的任何操作都是对实参数组的操作。此在被调函数中对形参数组的任何操作都是对实参数组的操作。5.3.2 函数调用中数组的传递函数调用中数组的传递1.形参为指针变量 主主调调函函数数使使用用数数组组名名作作为为实实参参时时,在在被被调调用用函函数数中中,形形参参可可以以是是用用于于存存放放地地址址的的指指针针变变量量。当当数数组组首首地地址址传传递递给给形形参参指指针针变变量量后后,该该指指针针变变量量就就指指向向了了数数组组的的存存储储空空间间。因因此此实实参参和和形形参参指指针针变变量量指指向向的的是是同同一一块块内内存存空空间间,在在被被调调用用函函数数中中,使使用用这这个个指指针变量就可以对主调函数中的所有数组元素进行处理。针变量就可以对主调函数中的所有数组元素进行处理。2形参为数组名 实参是数组名时,形参还可以是数组名,此时形参数组名实参是数组名时,形参还可以是数组名,此时形参数组名接收的是实参数组的首地址,由此可知,形参数组和实参数组接收的是实参数组的首地址,由此可知,形参数组和实参数组仍然共用同一块内存空间,因此对形参数组的任何操作就是对仍然共用同一块内存空间,因此对形参数组的任何操作就是对实参数组的操作。实参数组的操作。3.形参为引用形参为引用 在对数组类型使用引用方式时,先用类型定义语句定义一在对数组类型使用引用方式时,先用类型定义语句定义一个个int型的数组类型,如下所示:型的数组类型,如下所示:typedef int array10;然后再使用然后再使用array来定义数组和引用。来定义数组和引用。#includevoid sort(int),output(int);void main()int a10,i;/*INPUT*/coutnInput data:;for(i=0;iai;output(a);sort(a);output(a);void sort(int x)int i,j,t;for(i=0;i9;i+)for(j=0;jxj+1)t=xj;xj=xj+1;xj+1=t;void output(int x)int i;coutThe datum are:n;for(i=0;i10;i+)coutxi“t”;coutn;数组名作参数例程数组名作参数例程1-1a0a(形参为数组名)(形参为数组名)(形参为数组名)(形参为数组名)x0 x#include#define SIZE 40void sort(int*),output(int*);void main()int aSIZE,i,n;/*INPUT*/coutn;for(i=0;iai;output(a,n);sort(a,n);output(a,n);void sort(int x,int n)int i,j,t;for(i=0;in-1;i+)for(j=0;jxj+1)t=xj;xj=xj+1;xj+1=t;void output(int x,int n)int i;coutThe datum are:n;for(i=0;in;i+)coutxi“t”;coutn;数组名作参数例程数组名作参数例程1-2(形参包括元素个数)(形参包括元素个数)(形参包括元素个数)(形参包括元素个数)void sort(int*px,int n)int i,j,t;for(i=0;in-1;i+)for(j=0;jpxj+1)t=pxj;pxj=pxj+1;pxj+1=t;void output(int*px,int n)int i;coutThe datum are:n;for(i=0;in;i+)coutpxi“t”;coutn;数组名作参数例程数组名作参数例程1-3#include#define SIZE 40void main()void sort(),output();int aSIZE,i,n;/*INPUT*/coutn;for(i=0;iai;output(a,n);sort(a,n);output(a,n);(形参为指针变量)(形参为指针变量)(形参为指针变量)(形参为指针变量)函数调用中的参数传递小结函数调用中的参数传递小结_当函数未被调用时,形参不占内存;当函数被调用当函数未被调用时,形参不占内存;当函数被调用时,为形参分配内存,并将实参的值传递给形参;时,为形参分配内存,并将实参的值传递给形参;返回时,释放形参所占内存返回时,释放形参所占内存_实参对形参的数据传递实参对形参的数据传递:是是“单向单向”、“值值”的传的传递,按照书写次序递,按照书写次序(与名字无关与名字无关)_实参可为任意常量、变量实参可为任意常量、变量(数组元素数组元素)、函数、表达、函数、表达式;还可为变量地址或式;还可为变量地址或数组名数组名。5.3.3 函数指针函数指针 一个函数在编译时被分配一个入口地址(第一条指令的地一个函数在编译时被分配一个入口地址(第一条指令的地址),可以将该地址赋给一个指针变量,这样,指针变量中存址),可以将该地址赋给一个指针变量,这样,指针变量中存储的就是该函数的入口地址,该指针就指向了该函数。这种指储的就是该函数的入口地址,该指针就指向了该函数。这种指向函数的指针变量,就简称函数指针。向函数的指针变量,就简称函数指针。函数指针定义的一般形式:函数指针定义的一般形式:数据类型数据类型(*指针变量名指针变量名)(形参列表形参列表);使用函数指针时,要注意的问题:使用函数指针时,要注意的问题:函数指针是一个指向函数的指针变量,它是专门用来存函数指针是一个指向函数的指针变量,它是专门用来存放函数的入口地址的,在程序中,给它赋予哪个函数的入口地放函数的入口地址的,在程序中,给它赋予哪个函数的入口地址,它就指向这个函数。因此,在一段程序中,一个函数指针址,它就指向这个函数。因此,在一段程序中,一个函数指针可被多次赋值,指向不同的函数。可被多次赋值,指向不同的函数。函数指针变量只能指向函数的入口地址,不能指向函数函数指针变量只能指向函数的入口地址,不能指向函数中某一条指令,因此,对一个函数指针中某一条指令,因此,对一个函数指针p,类似,类似p+n,p+,p-的运算是无意义的。的运算是无意义的。5.3.3 函数指针函数指针例:使用函数指针的例子例:使用函数指针的例子#include int func(int a,int b);void main()int(*pf)(int a,int b);/定义一个函数指针变量定义一个函数指针变量pf pf=func;/将函数将函数func的入口地址赋给函数指针的入口地址赋给函数指针pf,从而使,从而使pf指向了该函数指向了该函数 cout please enter two integers:m n;int result=(*pf)(m,n);/等价执行等价执行result=func(5,10)cout result is result endl;int func(int a,int b)return a+b;5.3.4 指针函数指针函数 指针函数是指函数的返回值为指针(地址)的函数。指针指针函数是指函数的返回值为指针(地址)的函数。指针函数定义格式为:函数定义格式为:数据类型数据类型*函数名函数名(参数表参数表);例如:例如:int*pf(int x,int y);其中其中pf是一个指针函数的函数名,它有两个是一个指针函数的函数名,它有两个int型参数,它的返型参数,它的返回值为回值为int*。指针函数在定义形式上与函数指针非常相像,它们的区别指针函数在定义形式上与函数指针非常相像,它们的区别在于一个有括号,一个没有括号,没有括号的是指针函数。在于一个有括号,一个没有括号,没有括号的是指针函数。在指针型函数中,使用在指针型函数中,使用return语句返回的可以是变量的地语句返回的可以是变量的地址、数组的首地址或指针变量,还可以是后面介绍的结构体、址、数组的首地址或指针变量,还可以是后面介绍的结构体、共用体等复合数据类型的首地址。共用体等复合数据类型的首地址。5.3.4 指针函数指针函数例:指针函数的一个应用实例,编写函数,当输入(例:指针函数的一个应用实例,编写函数,当输入(112)月)月份时,输出相应月份的英文名称份时,输出相应月份的英文名称#includechar*month_name(int n);void main()int i;cini;coutitmonth_name(i)endl;/调用函数调用函数char*month_name(int n)char*name=illegal month,January,February,March,April,May,June,July,August,September,October,November,December;return(n12)?name0:namen);5.4 函数的嵌套调用函数的嵌套调用main()调用调用a函数函数.a 函数函数调用调用b函数函数b函数函数 嵌套调用就是在某一个被调用函数执行过程中,又可以嵌套调用就是在某一个被调用函数执行过程中,又可以对另一个函数进行调用。也就是说,函数在执行过程中,可对另一个函数进行调用。也就是说,函数在执行过程中,可以在任何需要的时候在被调函数中对其他函数进行调用。以在任何需要的时候在被调函数中对其他函数进行调用。#includedouble area(double,double,double);void main()double a,b,c,s;coutabc;s=area(a,b,c);cout“area=“s“n”;#include double area(double x,double y,double z)double s;if(x+yz|x+zy|y+z1n!=#includevoid main()int n;double y;cinn;if(n0)coutn0,data error!;elsey=fac(n);coutn“!=“y;直接调用直接调用(1)写出调用终止条件)写出调用终止条件(2)写出计算公式)写出计算公式用递归方法求用递归方法求n!(3!)double fac(int n)f=fac(n-1)*n;return f;void main()y=fac(n);double fac(int n)f=fac(n-1)*n;return f;double fac(int n)if(n=0|n=1)f=1;return f;3211 12 26 6v执行过程执行过程5.6 内联函数和重载函数内联函数和重载函数 5.6.1 内联函数内联函数1内联函数的引入内联函数的引入 函数调用是以降低效率为代价的,在程序执行过程中,调用函数时首先需要保存主调函数的现场和返回值,然后程序转移到被调函数的起始地址开始执行。被调函数执行结束后,先恢复主调函数的现场,取出返回地址并将返回值赋给函数调用本身,最后在返回地址处开始继续执行。对于函数体比较小且执行的功能比较简单的函数,如果反复多次调用,系统的开销还是比较大的。为了解决这一问题,C+引入了内联函数的概念。使用内联函数,编译器在编译时,并不生成普通的函数,而是将程序中出现的内联函数的调用表达式用该内联函数的函数体进行替换。这样处理虽然会增加目标代码量,但是不会产生由于函数调用而引起的在时间和空间中的转来转去。由于内联函数一般代码量不大,对其效率影响较小。因此,对代码量小访问频繁的函数,可以采用内联函数的方式,这样有助于提高效率。5.6.1 内联函数内联函数2内联函数的定义内联函数的定义定义内联函数的方法是在函数头前加关键字定义内联函数的方法是在函数头前加关键字inline inline int aver(int x,int y)return(x+y)/2;函数函数aver就是一个内联函数就是一个内联函数例:用内联函数计算圆面积。例:用内联函数计算圆面积。#include inline double CircleArea(double r)return 3.14*r*r;void main()double r=3.0;/r是圆的半径是圆的半径 double area=CircleArea(r);/调用内联函数,编译时被替换为函数体语句调用内联函数,编译时被替换为函数体语句 coutareaendl;5.6.1 内联函数内联函数 内联函数也遵循定义在前,调用在后的原则。形参内联函数也遵循定义在前,调用在后的原则。形参和实参之间的关系与一般函数相同。和实参之间的关系与一般函数相同。内联函数内不允许有循环语句、内联函数内不允许有循环语句、switch开关语句和开关语句和复杂嵌套的复杂嵌套的if语句,如果内联函数含有这些语句,则语句,如果内联函数含有这些语句,则按普通函数处理。按普通函数处理。内联函数的函数体一般不宜过大,以内联函数的函数体一般不宜过大,以15行为宜。行为宜。递归函数不能被用做内联函数。递归函数不能被用做内联函数。在类结构中,在类体内定义的成员函数都是内联函在类结构中,在类体内定义的成员函数都是内联函数。数。3使用内联函数应注意的事项使用内联函数应注意的事项 内联函数与一般函数的区别,简单讲就