函数
函数的声明
编程中的函数(function)一般是若干语句的集合。我们也可以将其称作“子过程(subroutine)”。在编程中,如果有一些重复的过程,我们可以将其提取出来,形成一个函数。函数可以接收若干值,这叫做函数的参数。函数也可以返回某个值,这叫做函数的返回值。
声明一个函数,我们需要返回值类型、函数的名称,以及参数列表。
// 返回值类型 int
// 函数的名称 some_function
// 参数列表 int, int
int some_function(int, int);
如上图,我们声明了一个名为 some_function
的函数,它需要接收两个 int
类型的参数,返回值类型也为 int
。可以认为,这个函数将会对传入的两个整数进行一些操作,并且返回一个同样类型的结果。
实现函数:编写函数的定义
只有函数的声明(declaration)还不够,他只能让我们在调用时能够得知函数的接口类型(即接收什么数据、返回什么数据),但其缺乏具体的内部实现,也就是函数的定义(definition)。我们可以在声明之后的其他地方编写代码实现(implement)这个函数(也可以在另外的文件中实现,但是需要将分别编译后的文件在链接时一并给出)。
如果函数有返回值,则需要通过 return
语句,将值返回给调用方。函数一旦执行到 return
语句,则直接结束当前函数,不再执行后续的语句。
int some_function(int, int); // 声明
/* some other code here... */
int some_function(int x, int y) { // 定义
int result = 2 * x + y;
return result;
result = 3; // 这条语句不会被执行
}
在定义时,我们给函数的参数列表的变量起了名字。这样,我们便可以在函数定义中使用这些变量了。
如果是同一个文件中,我们也可以直接将声明和定义合并在一起,换句话说,也就是在声明时就完成定义。
int some_function(int x, int y) {
return 2 * x + y;
}
如果函数不需要有返回值,则将函数的返回值类型标为 void
;如果函数不需要参数,则可以将参数列表置空。同样,无返回值的函数执行到 return;
语句也会结束执行。
void say_hello() {
cout << "hello!\n";
cout << "hello!\n";
cout << "hello!\n";
return;
cout << "hello!\n"; // 这条语句不会被执行
}
函数的调用
和变量一样,函数需要先被声明,才能使用。使用函数的行为,叫做“调用(call)”。我们可以在任何函数内部调用其他函数,包括这个函数自身。函数调用自身的行为,称为递归(recursion)。
在大多数语言中,调用函数的写法,是函数名称加上一对括号 ()
,如 foo()
。如果函数需要参数,则我们将其需要的参数按顺序填写在括号中,以逗号间隔,如 foo(1, 2)
。函数的调用也是一个表达式,函数的返回值就是表达式的值。
函数声明时候写出的参数,可以理解为在函数当前次调用的内部可以使用的变量,这些变量的值由调用处传入的值初始化。看下面这个例子:
int foo(int, int);
/* ... */
void foo(int x, int y) {
x = x * 2;
y = y + 3;
}
/* ... */
a = 1;
b = 1;
// 调用前:a = 1, b = 1
foo(a, b); // 调用 foo
// 调用后:a = 1, b = 1
在上面的例子中,foo(a, b)
是一次对 foo
的调用。调用时,foo
中的 x
和 y
变量,分别由调用处 a
和 b
的值初始化。因此,在 foo
中对变量 x
和 y
的修改,并不会影响到调用处的变量的值。
如果我们需要在函数(子过程)中修改变量的值,则需要采用“传引用”的方式。
void foo(int& x, int& y) {
x = x * 2;
y = y + 3;
}
/* ... */
a = 1;
b = 1;
// 调用前:a = 1, b = 1
foo(a, b); // 调用 foo
// 调用后:a = 2, b = 4
上述代码中,我们看到函数参数列表中的“int
”后面添加了一个“&
(and 符号)”,这表示对于 int
类型的引用(reference)。在调用 foo
时,调用处 a
和 b
变量分别初始化了 foo
中两个对 int
类型的引用 x
和 y
。在 foo
中的 x
和 y
,可以理解为调用处 a
和 b
变量的“别名”,即 foo
中对 x
和 y
的操作,就是对调用处 a
和 b
的操作。
main
函数
特别的,每个 C/C++ 程序都需要有一个名为 main
的函数。任何程序都将从 main
函数开始运行。
main
函数也可以有参数,通过main
函数的参数,我们可以获得外界传给这个程序的指令(也就是“命令行参数”),以便做出不同的反应。
下面是一段调用了函数(子过程)的代码:
// hello_subroutine.cpp
#include <iostream>
void say_hello() {
std::cout << "hello!\n";
std::cout << "hello!\n";
std::cout << "hello!\n";
}
int main() {
say_hello();
say_hello();
}