#Z0301. 讲解自定义函数
讲解自定义函数
No testdata at current.
这一章,我们将向大家介绍 C++ 编程语言中,函数的概念、定义与调用。
大家在数学中已经接触过 函数 这个概念——但在程序设计中,所谓“函数”,指的是一个事先定义好的代码模块,一经定义,就可以在程序的多个位置重复调用。我们之前使用的诸如 size、pow 等等,就是 C++ 各类库中已经定义好的函数。
在程序开发过程中,一个较为复杂的系统往往需要划分为若干个子系统,然后对这些子系统,或者说子程序,分别进行开发和调试。在 C++ 语言中,这种子程序体现为函数。 函数编写好之后,就可以被重复使用——使用的时候用户只需要关心函数的功能和用法,而不用具体考虑怎么实现函数的功能。这样有利于代码重用,可以有效提高开发效率,增强程序的可靠性,也便于分工合作和维护。
为什么要写函数
我们来看下面这段代码:
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= i; j++) {
cout << '*';
}
cout << endl;
}
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= i; j++) {
cout << '*';
}
cout << endl;
}
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= i; j++) {
cout << '*';
}
cout << endl;
}
程序会依次输出三个直角三角形。但是,这个程序看起来很“傻瓜”,写出了三段极为相似的二重循环。我们有没有办法把这段代码精简一下呢?
精简后的程序
void output(int n) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
cout << '*';
}
cout << endl;
}
}
int main() {
output(3);
output(4);
output(5);
return 0;
}
那么,这里的void
又是什么意思呢?为什么要写出void output(int n) {
这样的一行代码呢?output(3)
被执行的时候发生了什么呢?
函数的定义
我们已经知道,在 C++ 语言中,任何变量在使用之前首先都要进行声明。同样地,任何函数在使用之前也要先完成定义。
简单地说,你要让编译器知道,你定义的这个函数里面究竟有什么代码需要执行,然后编译器才能在你调用函数的时候,知道接下来该做什么。
对于如下的函数定义:
void output(int n) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
cout << '*';
}
cout << endl;
}
}
其中,output
为函数名,int n
为形式参数表。形式参数表 说明了函数输入的每个参数的类型和名称,其声明方式与变量的声明类似。内部的两重循环为函数体语句,在这部分语句中,可以用形式参数表中的变量(如变量n
)进行各种操作。
我们一般将void output(int n) {}
称为函数的头部。
形参和实参
如果有多个形式参数(简称为 形参),则用逗号分隔即可,每个形式参数的类型都要明确写出,不能省略:
void abc(int a, int b, int c) {
}
形参的取值决定于调用这个函数的代码。例如,我们可以在主函数调用刚刚定义的输出三角形的output
函数:
output(3);
output(4);
output(5);
每次调用的代码output(3)
中的 3 就是 实际参数(简称 实参)。当我们指定实际参数为 3 之后,output
函数的函数体语句中就可以认为形参变量n
的初始值为 3,也就可以输出一个大小为 3 的直角三角形了。
函数的形参一定要和实参一一对应,参数个数和对应位置的参数类型完全相同。
数组参数
当我们需要使用数组作为参数时,可以这么写:
void sum(int arr[], int n) {
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
这个函数会输出一个有 n 个int
类型元素的数组,当我们执行如下的调用语句后:
int a[] = {2, 3, 1, 4, 7, 6};
output(a, 4);
会输出:2 3 1 4
。在实参中,我们可以传入一个值、一个变量、甚至一个式子(函数的形参有另外一种传递参数的方式,此时的实参必须为一个变量,不在本节课中展开介绍了)。
无参数函数
当一个函数没有任何形参时,可以按照如下的方式定义:
void hello() {
int x;
cin >> x;
cout << "hello " << x + 1 << endl;
}
int main() {
hello();
return 0;
}
无论是函数的定义还是调用,函数名后的一对小括号都是必不可少的。如果不加这对小括号,会导致编译错误哦。
函数内修改参数
在函数内修改形参的值,是不一定会对实参的值产生影响的。比如下面这段代码:
void add(int x) {
x++;
}
int main() {
int a = 5;
add(a); // a == 5
return 0;
}
执行add(a)
之后,a
的值仍然为 5 而不是 6。对于int
、string
、double
、char
等类型的形参,都是如此。
只要当形参类型为数组时,修改形参的值会对应地修改实参的值:
void add(int a[]) {
a[0]++;
}
int main() {
int x[5] = {2, 3, 4, 5, 6};
add(x); // x == {3, 3, 4, 5, 6}
return 0;
}
一定不要搞混哦。