章节目录

函数简介

本节阅读量:

上一章中,我们将函数定义为按顺序执行的语句集合。虽然这个定义是正确的,但它没有揭示函数为什么有用。让我们更新一下函数的定义:函数是一个可重用的语句序列,旨在完成特定的工作。

每个可执行程序都必须有一个名为main的函数(程序运行时从这里开始执行)。然而,随着程序变得越来越长,将所有代码放在主函数中会变得难以管理。函数提供了一种方法,可以将程序划分为较小的模块,这些模块更易于组织、测试和使用。C++标准库附带了许多已编写好的函数供使用——当然,编写自己的函数也很常见。自己编写的函数称为用户定义函数。

考虑一个现实生活中的场景:你正在读书时,需要打个电话。你在书中放了一个书签,打完电话后,回到书签的位置,继续读书。

C++程序以相同的方式工作。函数内的语句按顺序执行。函数调用是一个表达式,告诉CPU中断当前函数并执行另一个函数。CPU在当前执行点”放置书签”,然后调用(执行)被调用的函数。当被调用的函数结束时,CPU返回到之前标记的点,继续执行。

发起函数调用的函数是调用者,而被调用的函数是被调用者或被调用函数。


用户定义函数的示例

首先,从定义函数的基本语法开始。接下来几节课中,所有用户定义函数将采用以下形式:

1
2
3
4
返回值类型 函数名() // 函数头,告知编译器函数的存在
{
    // 函数体
}

第一行称为函数头,它告诉编译器函数的存在、函数的名称以及将在后续课程中介绍的一些其他信息(如返回类型和参数类型)。

  1. 本课中,返回值类型使用int(对于函数main())或void。下一课中将更多讨论返回类型和返回值,现在可以先忽略这些。
  2. 就像变量有名称一样,用户定义函数也有名称。「函数名」是用户定义函数的名称(标识符)。
  3. 标识符后面的括号告诉编译器在定义函数。

中间的花括号和语句称为函数体,其中包含决定函数执行什么操作的语句。

下面的示例程序展示了如何定义和调用新函数:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <iostream>

// 用户自定义函数 doPrint()
void doPrint() // doPrint() 是被调函数
{
    std::cout << "In doPrint()\n";
}

// 定义函数 main()
int main()
{
    std::cout << "Starting main()\n";
    doPrint(); // 去执行函数 doPrint().  main() 是调用者.
    std::cout << "Ending main()\n"; // doPrint() 执行结束后,返回这里继续执行

    return 0;
}

该程序产生以下输出:

1
2
3
Starting main()
In doPrint()
Ending main()

程序从函数main开始执行,第一行打印Starting main()。

main中的第二行是对函数doPrint的函数调用。通过在函数名后附加一对括号来调用函数doPrint,如:doPrint()。注意,如果忘记括号,程序将无法编译。

由于进行了函数调用,main中语句的执行被挂起,执行跳转到被调用函数doPrint的顶部。doPrint中的第一行(也是唯一一行)打印In doPrint()。当doPrint终止时,执行返回给调用方(main函数),并从中断的位置恢复。因此,main中执行的下一条语句打印Ending main()。


多次调用函数

函数的一个好处是可被多次调用。演示如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include <iostream>
void doPrint()
{
    std::cout << "In doPrint()\n";
}

int main()
{
    std::cout << "Starting main()\n";
    doPrint(); // doPrint() 第一次调用
    doPrint(); // doPrint() 第二次调用
    std::cout << "Ending main()\n";

    return 0;
}

该程序输出:

1
2
3
4
Starting main()
In doPrint()
In doPrint()
Ending main()

由于main调用了doPrint两次,所以doPrint执行了两次,In doPrint() 也打印了两次(每次调用一次)。


被调用的函数,再调用函数

函数main可以调用另一个函数(例如上面例子中的函数doPrint)。实际上,任何函数都可以调用任何其他函数。如下程序中,函数main调用函数doA,而doA又调用函数doB:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

void doB()
{
    std::cout << "In doB()\n";
}


void doA()
{
    std::cout << "Starting doA()\n";

    doB();

    std::cout << "Ending doA()\n";
}

// Definition of function main()
int main()
{
    std::cout << "Starting main()\n";

    doA();

    std::cout << "Ending main()\n";

    return 0;
}

该程序产生以下输出:

1
2
3
4
5
Starting main()
Starting doA()
In doB()
Ending doA()
Ending main()

不支持嵌套函数定义

与一些编程语言不同,C++中,函数不能在其他函数中定义。以下程序不合法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <iostream>

int main()
{
    void foo() // 不合法,不允许在函数中定义函数
    {
        std::cout << "foo!\n";
    }

    foo();
    return 0;
}

正确方法是:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <iostream>

void foo()
{
    std::cout << "foo!\n";
}

int main()
{
    foo();
    return 0;
}

1.11 第1章总结

上一节

2.1 函数返回值

下一节