6.1 函数基础
函数是一个命名了的代码块,我们通过调用函数执行相应的代码。函数可以有 0 个或多个参数,而且(通常)会产生一个结果。可以重载函数(同一个名字可以对应几个不同的函数)。
一个典型的函数(function)定义包括以下几个部分:
- 返回类型(return type)
- 函数名字
- 由 0 个或多个形参(parameter)组成的列表
- 函数体
编写函数
// val 的阶乘是 val * (val-1) * (val-2)... * ((val - (val - 1)) * 1)
int fact(int val)
{
int ret = 1; // 局部变量,用于保存计算结果
while (val > 1)
ret *= val--; // 把 ret 和 val 的乘积赋给 ret,然后将 val 减 1
return ret; // 返回结果
}
调用函数
int main()
{
int j = fact(5); // 调用函数 fact()
cout << j << endl;
return 0;
}
函数的调用完成两项工作:
- 用实参初始化函数对应的形参;
- 将控制权转移给被调用函数。
形参和实参
实参是形参的初始值。
实参的类型必须与对应的形参类型匹配。
函数的形参列表
函数的形参列表可以为空,但不能省略。
void f1() { /*...*/ } // 隐式地定义空形参列表
void f2(void) { /*...*/} // 显式的定义空形参列表
形参列表中的形参通常用逗号隔开,其中每个形参都是含有一个声明符的声明。必须把形参的全部类型写出来。
任意两个形参都不能同名,而且函数最外层作用域中的局部变量也不能使用与函数形参一样的名字。
函数返回类型
函数的返回类型不能是数组类型或者函数类型,但可以是指向数组或函数的指针。
6.1.1 局部对象
名字有作用域,对象有生命周期。
- 名字的作用域是程序文本的一部分,名字在其中可见。
- 对象的生命周期是程序执行过程中该对象存在的一段时间。
形参和函数体内部定义的变量统称为局部变量,仅在函数的作用域内可见。同时局部变量还会隐藏在外层作用域中同名的其他所有声明。
自动对象
只存在于块执行期间的对象称为自动对象(automatic object)。
局部静态对象
局部静态对象在程序的执行路径第一次经过对象定义语句时初始化,并且直到程序终止才被销毁。
size_t count_calls(){
static size_t ctr = 0; // 调用结束后,这个值仍然有效
return ++ctr;
}
int main(){
for (size_t i = 0; i != 10; ++i){
cout << count_calls() << endl;
}
return 0;
}
如果局部静态变量没有显式的初始值,它将执行值初始化,内置类型的局部静态变量初始化为 0。
6.1.2 函数声明
函数的名字必须在使用之前声明。
函数的声明无需函数体,用一个分号替代。
因为函数的声明不包含函数体,所以也就无需形参的名字。
函数声明也称作函数原型(function prototype)。
在头文件中进行函数声明
函数应该在头文件中声明而在源文件中定义。
含有函数声明的头文件应该被包含到定义函数的源文件中。
6.1.3 分离式编译(separate compilation)
编译和链接多个源文件