C++语言程序设计 第五章 函数
第五章 函数
5.1 函数的定义
5.2 函数的调用
5.3 函数的嵌套调用
5.4 递归函数
5.5 作用域与生命期
C++语言程序设计 第五章 函数
5.1函数的定义
一般形式为,
数据类型 函数名(形参表)
{
语句序列;
}
其中,
1.数据类型 规定了函数返回值的类型,若 函数执行后不返回值, 数据类型习惯用
void 来表示 。 如果在函数定义时没有数据类型出现,则默认表示函数返回一个整型值 。
2.函数名
函数名是一个有效的 C++标识符 。 在 C++程序中, 除了 main函数外, 其它的函数名可
用户自行定义 。 为养成良好的程序设计风格, 应给函数命名一个能反映函数功能, 有助
于记忆的标识符 。
5.1.1函数的定义
C++语言程序设计 第五章 函数
3,形参表
形参表,是用逗号隔开的一个变量名说明列表,这些变量称作函数的形参,用于在
函数调用时传送数据。在函数定义中,形参的个数是按函数需要而设定的,也可以
没有形参。对于没有形参的函数,形参表用 void表示,此时也可省略形参表,但函
数名之后的一对圆括号不可省略。根据函数定义中有无形参,可将函数分为两类:
无参函数与有参函数。
每个参数必须同时说明参数类型和参数名,其一般形式为,
数据类型 变量名 1,数据类型 变量名 2,.....,数据类型 变量名 N
4,函数体
由花括号所括起的语句序列称为函数体。它定义了函数为完成某项功能所要执行的具体
操作。这些操作,既可以用语句来描述,也可以通过调用另一些已定义的函数来实现。也就
是说,函数体中既包含 C++中的语句,也可以调用其它函数( main函数除外)。当函数执行结
束需要返回一个值时,在这个函数体中还必须有一个 return语句。
C语言还允许出现函数体为空的函数, 称之为空函数 。 如,
empty()
{
}
C++语言程序设计 第五章 函数
5.1.2 函数原型
C++语言规定:函数名必须先说明后使用。因此,当对一个函数的调用
出现在该函数定义之前时,必须先对函数进行原型说明。
函数原型也称函数模式。 C++要求为程序中所有函数构造原型。函数原
型标识一个函数的返回值类型,同时也标识出该函数参数的个数和类型。
为函数构造原型非常简单,在 C++程序中,可使用与函数定义中的函数
说明相同的格式来说明一个函数原型 。
数据类型 函数名(参数类型说明列表) ;
其中, 参数类型说明列表, 是用逗号隔开的一个参数类型说明,其参数
个数和指定的类型必须和函数定义中的参数个数和类型一致。由于函数
原型是一条语句,因此函数原型必须以分号结束。函数原型不必包含参
数的名字,可只包含参数的类型。
C++语言程序设计 第五章 函数
5.2 函数的调用
C++语言程序设计 第五章 函数
函数调用一般格式为,
函数名 ( 实参表 )
函数调用时提供的参数称为实在参数, 简称实参 。 实参表可包含多个实参, 它
们之间用逗号隔开, 实参可以是常量, 变量, 也可以是表达式 。 实参按它们出现
的顺序, 类型及个数要与形参一一对应 。
无参函数的调用形式为,
函数名 ()
其中函数名之后的一对圆括号是不能省略的 。
按函数调用在程序中的作用, 有两种不同类型的应用,
一是函数调用只是利用函数所完成的功能 。 此时, 将函数调用作为一个独立的
语句 。 这种应用不要求函数返回值 。
二是函数调用是利用函数的返回值 。 或用这返回值继续进行表达式的计算, 或
输出函数返回值等 。
比如,
w = min(u+v,a-b) + min(c,t) + 3.9;
cout<< min(u -v,a+b));
5.2.1 函数的调用
C++语言程序设计 第五章 函数
函数调用的执行过程描述如下,
(1)为函数的形参分配内存空间;
(2)计算实参表达式的值, 并将实参表达式的值赋给对应的
形参;
(3)执行函数体内的语句序列;
(4)函数体执行完, 或执行了函数体内的 return语句 ( 若
return语句带表达式, 则计算出该表达式的值, 并以此值作
为函数值 ) 后, 释放为这次函数调用分配的全部内存空间;
(5)将函数值 ( 如果有 ) 返回到函数调用处继续执行 。
C++语言程序设计 第五章 函数
【 例 5.4】 计算变量 a,b之和 。
#include <iostream.h>
int sum(int x,int y)
{
int temp;
temp = x+y;
return temp;
}
void main( )
{
int a,b,c;
a = 10; b = 5;
c = sum(a,b);
cout << c;
}
程序运行结果为,
15
main( ) 为主调函数, sum( )
为被调用函数 。 函数调用表
达式 sum( a,b) 的类型为
int型 。 在函数调用过程中,
实参 a的值 10赋给了形参 x,
实参 b的值 5赋给了形参 y,程
序转去执行函数 sum( ) 中的
第一条语句 。 return语句将
求和结果返回主调函数, 返
回值为 15,这个值就是调用
表达式的值,可以作为操作数
在表达式中参与运算 ( 给变
量 c赋值 ) 。 函数的调用过程
如图所示 。
C++语言程序设计 第五章 函数
void main( )
{
int a,b,c;
a = 10; b = 5;
c = sum(a,b);
cout << c;
}
int sum(int x,int y)
{
int temp;
temp= x+y;
return temp;
}
a?x,b?y
返回 15
函数调用过程
C++语言程序设计 第五章 函数
5.2.2 参数传递机制
函数调用时,主调函数与被调用函数之间要进行数据传递 。 在 C++中, 可以使用两种不
同的参数传递机制来实现 。 一种称为, 传值, ( 值调用 ), 另一种称为引用调用,
【 例 5.6】 输入两个整数, 比较大小, 输出较大的数 。 ( 求最大值用函数 max实现 )
#include <iostream.h>
int max ( int u,int v)
{ 传值
int w;
w = u > v? u:v;
return w;
}
void main ( )
{
int a,b,c;
cin >> a >> b;
c = max(a,b); Main函数 max函数
cout << "a =" << a << "b ="<< b << endl;
cout << "Max is " << c;
}
a
b
u
v
3
5 5
3
C++语言程序设计 第五章 函数
5.2.3 函数返回值
利用 return语句可以把被调用函数的操作结果传递回主调函数 。
return是流程控制语句 。 它包含在函数体中, 其一般语法格式为,
return ( 表达式 );
当函数执行 return语句或执行完函数体的语句序列后, 函数的这次调用就执行结束
随之将控制返回到函数调用处继续执行 。
【 例 5.8】 void类型函数中 return语句的作用 。
#include <iostream.h>
void display(int x,float y)
{
cout << x << " "<< y;
return;
}
void main()
{
float a;
int b;
cin >> b >> a;
display(b,a);
}
C++语言程序设计 第五章 函数
5.3 函数的嵌套调用
在 C++语言中, 所有的函数从定义关系上来看是平等的, 也就是说在定义函数时,
一个函数体内不能包含另一个函数的定义 。 但从调用关系上来看, 函数之间就存
在一种关系叫嵌套调用 。 这种关系表现为在某一个被调用函数执行过程中, 又可
以对另一个函数进行调用 。 也就是说, 函数在执行过程中, 不是执行完一个函数
再去执行另一个函数, 而是可以在任何需要的时候对其它函数进行调用, 这就是
函数的嵌套调用 。 下面看一个模拟的例子,
int a( );
int b( );
main( )
{,.,
a( );
}
int a( )
{,.,
b( );
}
int b( )
{...}
main函数 a函数 b函数
a函数结束 结束 b函数结束
调用 a函数 调用 b函数
①
②
③
④
⑤
⑥
⑦
⑧ ⑨
图 5.5 两层嵌套的执行过程
C++语言程序设计 第五章 函数
5.4 递归函数
定义
一个函数在它的函数体内
直接或间接调用它自身称
为函数的递归调用,在调用
过程中主调函数又称被调
函数,执行递归函数将反复
调用其自身,每调用一次就
进入新的一层,
一个问题能否用递归实现, 看其是否具
有下 面的特点,
(1) 需有完成任务的递推公式 。
(2) 结束递归的条件 。
编写递归函数时, 程序中必须有相应的
语句,
(1) 一个递归调用语句 。
(2) 判断结束语句。先判断条件决定是
否递归调用。
C++语言程序设计 第五章 函数
5.5 作用域与生命期
?1,函数原型作用域
?2,块作用域
?3,函数作用域
?4.类作用域
?5,文件作用域
1,函数原型作用域
这是 C++中最简单的一种作用域, 这个作用域开始于函数原型说明的左括号, 结束于函
数原型说明的右括号处 。 例如下面的函数原型说明,
double Calnumber (double number);
其中 double number只在圆括号内是有效的, 在程序代码的其它地方
2,块作用域
块是函数中一对花括号 ( 包括函数定义所使用的花括号 ) 所括起的一段代码区
域 。 在块内说明的标识符具有块作用域, 它开始于标识符被说明的地方, 并在标
志该块结束的右花括号处结束 。
C++语言程序设计 第五章 函数
3,函数作用域
具有函数作用域的标识符在该函数内的任何地方可见 。 在 C++中, 只有
goto语句的标号具有函数作用域 。 这个标识符由下述语法形式进行声明,
标号:语句
在函数中做了上述声明后,所声明的标号就可在函数内的任何位置被引
用。
5,文件作用域
在函数和类之外说明的标识符具有文件作用域 。 文件作用域从说明点开
始, 在文件尾处结束 。 在前面我们所见到的所有程序中,关于函数定义和函
数原型都是在文件作用域中进行的声明, 所以, 所声明的函数名具有文件
作用域 。
在一个文件作用域中,可能包含着其它类型的作用域 ( 函数作用域, 块作
用域, 类作用域 ) 。 标识符的声明规则为在同一作用域中不能声明相同的
标识符;但在不同的作用域中可包含同一个标识符 。 因此, 若某个程序中
含有多个作用域, 可能会出现同名标识符情况 。
C++语言程序设计 第五章 函数
5.5.2 全局变量和局部变量
变量可以在文件作用域或块作用域中声明, 在文件作用域中声明的变量称全
局变量, 在块作用域中声明的变量称局部变量 。
1,局部变量
一般来说, 在一个函数内部声明的变量为局部变量, 其作用域只在本函
数范围内 。 也就是说, 局部变量只能在定义它的函数体内部使用, 而不能在
其它函数内使用这个变量 。
char f2 (int x,int y) // 形参 x,y在函数内定义, 属于局部变量
{
int i,j,b,c; // i,j,b,c均是函数 f2的局部变量
..,
}
void main ( )
{
int m,n; // m,n是主函数的局部变量, 只在 main中有效
..,
}
C++语言程序设计 第五章 函数
2.全局变量
在文件作用域中声明的变量称作全局变量。全局变量的作用域是从声明该变量
的语句位置开始,直至本文件结束。因而全局变量声明后可以被很多函数使用。
5.5.3 生命期
程序中的各种变量都有一个在需要时被创建, 而在不需要时被删除的
过程 。 在创建和删除之间所经过的时间就被称为生命期 。
1.局部变量的存储方式
⑴ 自动的( auto)存储方式。
⑵ 静态的( static)存储方式。
(3) 寄存器( register)存储方式
2.全局变量的存储方式
全局变量采用静态存储方式, 放在程序的静态存储区 。 通常, 一个程
序可以由多个源程序文件组成 。 根据某个文件中的全局变量是否能被其
它源程序文件使用, 又将全局变量分为外部的和内部的 。
C++语言程序设计 第五章 函数
3,存储方式小结
从作用域角度来看, 变量可分为全局变量和局部变量 。
对于局部变量, 若使用 static说明 ( 静态局部变量 ), 则其
存储方式为静态存储方式, 存放在静态存储区;未加说明
的局部变量, 一般为自动变量, 使用动态存储方式, 存放
在动态存储区, 函数结束后释放其存储空间 。
对于全局变量,均使用静态存储方式 。 使用 static声明的
全局变量, 只限在本文件中使用;未加 static说明, 使其在
全部源程序文件中均可以引用 。
C++语言程序设计 第五章 函数
第五章 函数
5.1 函数的定义
5.2 函数的调用
5.3 函数的嵌套调用
5.4 递归函数
5.5 作用域与生命期
C++语言程序设计 第五章 函数
5.1函数的定义
一般形式为,
数据类型 函数名(形参表)
{
语句序列;
}
其中,
1.数据类型 规定了函数返回值的类型,若 函数执行后不返回值, 数据类型习惯用
void 来表示 。 如果在函数定义时没有数据类型出现,则默认表示函数返回一个整型值 。
2.函数名
函数名是一个有效的 C++标识符 。 在 C++程序中, 除了 main函数外, 其它的函数名可
用户自行定义 。 为养成良好的程序设计风格, 应给函数命名一个能反映函数功能, 有助
于记忆的标识符 。
5.1.1函数的定义
C++语言程序设计 第五章 函数
3,形参表
形参表,是用逗号隔开的一个变量名说明列表,这些变量称作函数的形参,用于在
函数调用时传送数据。在函数定义中,形参的个数是按函数需要而设定的,也可以
没有形参。对于没有形参的函数,形参表用 void表示,此时也可省略形参表,但函
数名之后的一对圆括号不可省略。根据函数定义中有无形参,可将函数分为两类:
无参函数与有参函数。
每个参数必须同时说明参数类型和参数名,其一般形式为,
数据类型 变量名 1,数据类型 变量名 2,.....,数据类型 变量名 N
4,函数体
由花括号所括起的语句序列称为函数体。它定义了函数为完成某项功能所要执行的具体
操作。这些操作,既可以用语句来描述,也可以通过调用另一些已定义的函数来实现。也就
是说,函数体中既包含 C++中的语句,也可以调用其它函数( main函数除外)。当函数执行结
束需要返回一个值时,在这个函数体中还必须有一个 return语句。
C语言还允许出现函数体为空的函数, 称之为空函数 。 如,
empty()
{
}
C++语言程序设计 第五章 函数
5.1.2 函数原型
C++语言规定:函数名必须先说明后使用。因此,当对一个函数的调用
出现在该函数定义之前时,必须先对函数进行原型说明。
函数原型也称函数模式。 C++要求为程序中所有函数构造原型。函数原
型标识一个函数的返回值类型,同时也标识出该函数参数的个数和类型。
为函数构造原型非常简单,在 C++程序中,可使用与函数定义中的函数
说明相同的格式来说明一个函数原型 。
数据类型 函数名(参数类型说明列表) ;
其中, 参数类型说明列表, 是用逗号隔开的一个参数类型说明,其参数
个数和指定的类型必须和函数定义中的参数个数和类型一致。由于函数
原型是一条语句,因此函数原型必须以分号结束。函数原型不必包含参
数的名字,可只包含参数的类型。
C++语言程序设计 第五章 函数
5.2 函数的调用
C++语言程序设计 第五章 函数
函数调用一般格式为,
函数名 ( 实参表 )
函数调用时提供的参数称为实在参数, 简称实参 。 实参表可包含多个实参, 它
们之间用逗号隔开, 实参可以是常量, 变量, 也可以是表达式 。 实参按它们出现
的顺序, 类型及个数要与形参一一对应 。
无参函数的调用形式为,
函数名 ()
其中函数名之后的一对圆括号是不能省略的 。
按函数调用在程序中的作用, 有两种不同类型的应用,
一是函数调用只是利用函数所完成的功能 。 此时, 将函数调用作为一个独立的
语句 。 这种应用不要求函数返回值 。
二是函数调用是利用函数的返回值 。 或用这返回值继续进行表达式的计算, 或
输出函数返回值等 。
比如,
w = min(u+v,a-b) + min(c,t) + 3.9;
cout<< min(u -v,a+b));
5.2.1 函数的调用
C++语言程序设计 第五章 函数
函数调用的执行过程描述如下,
(1)为函数的形参分配内存空间;
(2)计算实参表达式的值, 并将实参表达式的值赋给对应的
形参;
(3)执行函数体内的语句序列;
(4)函数体执行完, 或执行了函数体内的 return语句 ( 若
return语句带表达式, 则计算出该表达式的值, 并以此值作
为函数值 ) 后, 释放为这次函数调用分配的全部内存空间;
(5)将函数值 ( 如果有 ) 返回到函数调用处继续执行 。
C++语言程序设计 第五章 函数
【 例 5.4】 计算变量 a,b之和 。
#include <iostream.h>
int sum(int x,int y)
{
int temp;
temp = x+y;
return temp;
}
void main( )
{
int a,b,c;
a = 10; b = 5;
c = sum(a,b);
cout << c;
}
程序运行结果为,
15
main( ) 为主调函数, sum( )
为被调用函数 。 函数调用表
达式 sum( a,b) 的类型为
int型 。 在函数调用过程中,
实参 a的值 10赋给了形参 x,
实参 b的值 5赋给了形参 y,程
序转去执行函数 sum( ) 中的
第一条语句 。 return语句将
求和结果返回主调函数, 返
回值为 15,这个值就是调用
表达式的值,可以作为操作数
在表达式中参与运算 ( 给变
量 c赋值 ) 。 函数的调用过程
如图所示 。
C++语言程序设计 第五章 函数
void main( )
{
int a,b,c;
a = 10; b = 5;
c = sum(a,b);
cout << c;
}
int sum(int x,int y)
{
int temp;
temp= x+y;
return temp;
}
a?x,b?y
返回 15
函数调用过程
C++语言程序设计 第五章 函数
5.2.2 参数传递机制
函数调用时,主调函数与被调用函数之间要进行数据传递 。 在 C++中, 可以使用两种不
同的参数传递机制来实现 。 一种称为, 传值, ( 值调用 ), 另一种称为引用调用,
【 例 5.6】 输入两个整数, 比较大小, 输出较大的数 。 ( 求最大值用函数 max实现 )
#include <iostream.h>
int max ( int u,int v)
{ 传值
int w;
w = u > v? u:v;
return w;
}
void main ( )
{
int a,b,c;
cin >> a >> b;
c = max(a,b); Main函数 max函数
cout << "a =" << a << "b ="<< b << endl;
cout << "Max is " << c;
}
a
b
u
v
3
5 5
3
C++语言程序设计 第五章 函数
5.2.3 函数返回值
利用 return语句可以把被调用函数的操作结果传递回主调函数 。
return是流程控制语句 。 它包含在函数体中, 其一般语法格式为,
return ( 表达式 );
当函数执行 return语句或执行完函数体的语句序列后, 函数的这次调用就执行结束
随之将控制返回到函数调用处继续执行 。
【 例 5.8】 void类型函数中 return语句的作用 。
#include <iostream.h>
void display(int x,float y)
{
cout << x << " "<< y;
return;
}
void main()
{
float a;
int b;
cin >> b >> a;
display(b,a);
}
C++语言程序设计 第五章 函数
5.3 函数的嵌套调用
在 C++语言中, 所有的函数从定义关系上来看是平等的, 也就是说在定义函数时,
一个函数体内不能包含另一个函数的定义 。 但从调用关系上来看, 函数之间就存
在一种关系叫嵌套调用 。 这种关系表现为在某一个被调用函数执行过程中, 又可
以对另一个函数进行调用 。 也就是说, 函数在执行过程中, 不是执行完一个函数
再去执行另一个函数, 而是可以在任何需要的时候对其它函数进行调用, 这就是
函数的嵌套调用 。 下面看一个模拟的例子,
int a( );
int b( );
main( )
{,.,
a( );
}
int a( )
{,.,
b( );
}
int b( )
{...}
main函数 a函数 b函数
a函数结束 结束 b函数结束
调用 a函数 调用 b函数
①
②
③
④
⑤
⑥
⑦
⑧ ⑨
图 5.5 两层嵌套的执行过程
C++语言程序设计 第五章 函数
5.4 递归函数
定义
一个函数在它的函数体内
直接或间接调用它自身称
为函数的递归调用,在调用
过程中主调函数又称被调
函数,执行递归函数将反复
调用其自身,每调用一次就
进入新的一层,
一个问题能否用递归实现, 看其是否具
有下 面的特点,
(1) 需有完成任务的递推公式 。
(2) 结束递归的条件 。
编写递归函数时, 程序中必须有相应的
语句,
(1) 一个递归调用语句 。
(2) 判断结束语句。先判断条件决定是
否递归调用。
C++语言程序设计 第五章 函数
5.5 作用域与生命期
?1,函数原型作用域
?2,块作用域
?3,函数作用域
?4.类作用域
?5,文件作用域
1,函数原型作用域
这是 C++中最简单的一种作用域, 这个作用域开始于函数原型说明的左括号, 结束于函
数原型说明的右括号处 。 例如下面的函数原型说明,
double Calnumber (double number);
其中 double number只在圆括号内是有效的, 在程序代码的其它地方
2,块作用域
块是函数中一对花括号 ( 包括函数定义所使用的花括号 ) 所括起的一段代码区
域 。 在块内说明的标识符具有块作用域, 它开始于标识符被说明的地方, 并在标
志该块结束的右花括号处结束 。
C++语言程序设计 第五章 函数
3,函数作用域
具有函数作用域的标识符在该函数内的任何地方可见 。 在 C++中, 只有
goto语句的标号具有函数作用域 。 这个标识符由下述语法形式进行声明,
标号:语句
在函数中做了上述声明后,所声明的标号就可在函数内的任何位置被引
用。
5,文件作用域
在函数和类之外说明的标识符具有文件作用域 。 文件作用域从说明点开
始, 在文件尾处结束 。 在前面我们所见到的所有程序中,关于函数定义和函
数原型都是在文件作用域中进行的声明, 所以, 所声明的函数名具有文件
作用域 。
在一个文件作用域中,可能包含着其它类型的作用域 ( 函数作用域, 块作
用域, 类作用域 ) 。 标识符的声明规则为在同一作用域中不能声明相同的
标识符;但在不同的作用域中可包含同一个标识符 。 因此, 若某个程序中
含有多个作用域, 可能会出现同名标识符情况 。
C++语言程序设计 第五章 函数
5.5.2 全局变量和局部变量
变量可以在文件作用域或块作用域中声明, 在文件作用域中声明的变量称全
局变量, 在块作用域中声明的变量称局部变量 。
1,局部变量
一般来说, 在一个函数内部声明的变量为局部变量, 其作用域只在本函
数范围内 。 也就是说, 局部变量只能在定义它的函数体内部使用, 而不能在
其它函数内使用这个变量 。
char f2 (int x,int y) // 形参 x,y在函数内定义, 属于局部变量
{
int i,j,b,c; // i,j,b,c均是函数 f2的局部变量
..,
}
void main ( )
{
int m,n; // m,n是主函数的局部变量, 只在 main中有效
..,
}
C++语言程序设计 第五章 函数
2.全局变量
在文件作用域中声明的变量称作全局变量。全局变量的作用域是从声明该变量
的语句位置开始,直至本文件结束。因而全局变量声明后可以被很多函数使用。
5.5.3 生命期
程序中的各种变量都有一个在需要时被创建, 而在不需要时被删除的
过程 。 在创建和删除之间所经过的时间就被称为生命期 。
1.局部变量的存储方式
⑴ 自动的( auto)存储方式。
⑵ 静态的( static)存储方式。
(3) 寄存器( register)存储方式
2.全局变量的存储方式
全局变量采用静态存储方式, 放在程序的静态存储区 。 通常, 一个程
序可以由多个源程序文件组成 。 根据某个文件中的全局变量是否能被其
它源程序文件使用, 又将全局变量分为外部的和内部的 。
C++语言程序设计 第五章 函数
3,存储方式小结
从作用域角度来看, 变量可分为全局变量和局部变量 。
对于局部变量, 若使用 static说明 ( 静态局部变量 ), 则其
存储方式为静态存储方式, 存放在静态存储区;未加说明
的局部变量, 一般为自动变量, 使用动态存储方式, 存放
在动态存储区, 函数结束后释放其存储空间 。
对于全局变量,均使用静态存储方式 。 使用 static声明的
全局变量, 只限在本文件中使用;未加 static说明, 使其在
全部源程序文件中均可以引用 。
C++语言程序设计 第五章 函数