2-1 函数介绍

在上章中,我们将函数定义为按顺序执行的语句集合。虽然这一定义没错,但它未能深入阐释函数的实用价值。让我们更新这个定义:函数function是为完成特定任务而设计的可复用语句序列。

你已经知道,每个可执行程序都必须包含一个名为 main() 的函数(程序运行时由此处开始执行)。然而随着程序日益复杂,将所有代码塞进main()函数变得难以管理。函数让我们能将程序拆解为小型模块化单元,更便于组织、测试和使用。大多数程序都使用大量函数。C++标准库提供了大量现成函数供你使用——但编写自定义函数同样常见。用户自行编写的函数称为用户定义函数user-defined functions

设想一个现实场景:你正在阅读书籍时突然想起需要打电话。你将书签夹入书中,完成通话后回到书签位置,精准接续阅读进度。

C++程序的运作原理与此类似(并沿用了部分术语)。当程序在某个函数内顺序执行语句时,若遇到函数调用function call,便会指示CPU中断当前函数执行,转而执行另一个函数。CPU本质上是在当前执行点“插入书签”,执行函数调用中指定的函数,随后returns返回书签标记的位置继续执行。

命名法
发起函数调用的函数称为调用方caller被调用called(执行)的函数称为被调用方callee。函数调用有时也称为调用invocation,即调用方调用invoking被调用方。


用户定义函数示例

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

returnType functionName() // This is the function header (tells the compiler about the existence of the function)
{
    // This is the function body (tells the compiler what the function does)
}

第一行被非正式地称为函数头function header,它向编译器告知函数的存在、函数名称以及其他将在后续课程中讲解的信息(如返回类型)。

  • 本节课中,我们将使用 int 作为返回类型returnType(针对 main() 函数),其他情况则使用 void。目前不必深究这些细节,我们将在下一课(2.2——函数返回值(值返回函数))中详细探讨返回类型与返回值。
  • 正如变量拥有名称,用户定义的函数同样需要命名。functionName即为用户定义函数的名称(标识符)。
  • 标识符后方的圆括号告知编译器我们正在定义函数。

花括号curly braces及其内部的语句称为函数体function body。这里将放置决定函数行为的语句。

调用函数时,需使用函数名后跟一组圆括号(例如 functionName() 调用名为 functionName 的函数)。按惯例,圆括号紧邻函数名放置(两者之间不留空格)。

目前函数必须先定义才能调用。我们在第2.7课——前向声明与定义中将探讨解决此限制的方法。

以下示例程序演示了用户自定义函数的定义与调用:

#include <iostream> // for std::cout

// Definition of user-defined function doPrint()
// doPrint() is the called function in this example
void doPrint()
{
    std::cout << "In doPrint()\n";
}

// Definition of user-defined function main()
int main()
{
    std::cout << "Starting main()\n";
    doPrint();                        // Interrupt main() by making a function call to doPrint().  main() is the caller.
    std::cout << "Ending main()\n";   // This statement is executed after doPrint() ends

    return 0;
}

该程序产生以下输出:

image

该程序从函数 main() 的顶部开始执行,首行代码将打印 Starting main()。

main() 中的第二行是对 doPrint() 函数的调用。我们通过末尾的括号判断这是函数调用。

警告
调用函数时,切勿遗漏函数名后的括号()。若遗漏括号,程序可能无法编译(即使编译成功,函数也不会被调用)。

由于函数调用发生,main()中的语句执行被暂停,控制流跳转至被调用函数doPrint()的开头。doPrint()中的第一行(也是唯一一行)输出“In doPrint()”。当doPrint()结束时,执行权限返回调用方(main()),并从函数调用后的位置继续执行。因此main()中下一条执行的语句输出“Ending main()”。


函数的多次调用

函数的一个实用特性在于它们可以被多次调用。以下程序演示了这一特性:

#include <iostream> // for std::cout

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

// Definition of function main()
int main()
{
    std::cout << "Starting main()\n";
    doPrint(); // doPrint() called for the first time
    doPrint(); // doPrint() called for the second time
    std::cout << "Ending main()\n";

    return 0;
}

该程序产生以下输出:

image

由于 main() 函数调用了两次 doPrint(),因此 doPrint() 被执行两次,并且在 doPrint() 中打印内容也会出现两次(每次调用各打印一次)。


函数可以调用其他函数,而被调用的函数又能继续调用其他函数

你已经看到主函数 main() 可以调用其他函数(如上例中的 doPrint() 函数)。被 main() 调用的函数同样可以调用其他函数(这些被调用的函数也能继续调用其他函数,如此循环往复)。在下面的程序中,主函数 main() 调用 doA() 函数,而 doA() 函数又调用 doB() 函数:

#include <iostream> // for std::cout

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;
}

该程序产生以下输出:

image


嵌套函数不受支持

将函数定义置于另一个函数内部即构成嵌套函数nested function。与某些编程语言不同,C++中不支持函数嵌套。以下程序是非合法的:

#include <iostream>

int main()
{
    void foo() // Illegal: this function is nested inside function main()
    {
        std::cout << "foo!\n";
    }

    foo(); // function call to foo()

    return 0;
}

image

上述程序的正确写法是:

#include <iostream>

void foo() // no longer inside of main()
{
    std::cout << "foo!\n";
}

int main()
{
    foo();

    return 0;
}

image

命名法:

“foo”是一个无意义的词,常被用作函数或变量的占位符名称,当名称对演示某些概念不重要时。此类词被称为元语法变量(尽管在日常语言中它们常被称为“占位符名称”,因为没人记得“元语法变量metasyntactic variable”这个术语)。C++中其他常见的元语法变量包括“bar”、“baz”以及以“oo”结尾的三字母词(如“goo”、“moo”、“boo”)。

对词源学(词汇演变过程)感兴趣者,可参阅RFC 3092获取有趣的阅读内容。


测验时间

问题 #1

在函数定义中,花括号及其内部的语句被称为什么?

显示答案

函数体

问题 #2

下列程序将输出什么?请勿编译此程序,仅需自行分析代码。

#include <iostream> // for std::cout

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

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

    doB();
}

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

    doA();
    doB();

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

    return 0;
}

显示答案

Starting main()
In doA()
In doB()
In doB()
Ending main()
posted @ 2026-02-08 23:02  游翔  阅读(1)  评论(0)    收藏  举报