🔷 第六章 函数
📄 一句话概括

嵌套调用 = 函数里再调用别的函数。它带来一条必须记牢的顺序规律——先进后出:最内层的函数最先执行完,然后一层层往外返回,像剥洋葱。进入时一层层往里钻,出来时一层层往外走,整个形状是一座对称的山。

📝 本节和前面几节的关系

6.3.1 讲了"跳进去、跳回来",这一节讲"跳进去之后又跳进别处"。它把 6.3 那个"调用栈"的机制用起来了:每跳进一个函数就在栈上记一笔,返回时按记住的顺序倒着来。搞懂这一节,下一节的递归才不会晕。

一、什么叫嵌套调用

void c() { cout << "C 干活" << endl; }                  // 第三层

void b() { cout << "B 开始"; c(); cout << "B 结束"; }     // 第二层,调 C

void a() { cout << "A 开始"; b(); cout << "A 结束"; }     // 第一层,调 B

int main() { a(); }                                     // 起点

输出顺序是:

A 开始
B 开始
C 干活
B 结束
A 结束

规律:进入时一层层往下钻,出来时一层层往上返——这就是"先进后出"(也叫后进先出)。

二、为什么必须先进后出(回看调用栈)

把 6.3 的"记位置"想象成一摞便签:

动作 便签堆
main 调 a 记下"main 停在 a() 这一行"
a 调 b 再记下"a 停在 b() 这一行"
b 调 c 再记下"b 停在 c() 这一行"
c 返回 撕掉最上面一张,回到 b
b 返回 再撕一张,回到 a
a 返回 再撕一张,回到 main

谁最后进去,谁最先出来——所以输出的形状必然是对称的。这不是巧合,是调用栈的物理属性。

三、嵌套调用的常见样子

场景 例子
分层处理 main → processAll() → processOne()
工具函数复用 printMenu() 里调 printLine()(6.2.1 的 Demo 就是这么干的)
表达式里层层调用 max(max(a, b), c) —— 这是写法上的嵌套,调用关系也是两层的
递归 自己调自己——嵌套调用最特殊的一种(6.3.3)

四、动手 Demo:三层嵌套看顺序

#include <iostream>
using namespace std;

void level3() { cout << "      第三层:干活" << endl; }

void level2() {
    cout << "    第二层:开始" << endl;
    level3();
    cout << "    第二层:结束" << endl;
}

void level1() {
    cout << "  第一层:开始" << endl;
    level2();
    cout << "  第一层:结束" << endl;
}

int main() {
    cout << "main:开始" << endl;
    level1();
    cout << "main:结束" << endl;
    return 0;
}

看到什么算成功:

main:开始
  第一层:开始
    第二层:开始
      第三层:干活
    第二层:结束
  第一层:结束
main:结束

用缩进看形状:前三行一层比一层深(往里钻),后三行一层比一层浅(往外返)——一座对称的山。

30 秒实验: 1. 把 level3() 的调用搬到 level1 的末尾,看输出形状怎么变——"嵌套"改的是深度,不是行数。 2. 在 level2() 里调用两次 level3(),观察那座"山"变成什么样(两个小尖峰)。

这个"看形状"的习惯,将来调试复杂程序时非常有用。

五、常见误区

  1. "嵌套调用就是在一行里塞很多括号"——不是。嵌套调用说的是"函数里调函数"(关系);一行里写很多层括号说的是"表达式嵌套"(写法)。两者可以同时出现,但不是一回事。
  2. "被调用的函数必须定义在调用者前面"——不必,有声明就行(6.1.2)。但定义顺序清晰更好读:习惯上把最底层的小工具写在前面。
  3. "嵌套层数越多越厉害"——反了,层数多意味着"读懂一处逻辑要翻好几个函数"(耦合高)。3 层以内最舒服,超过就该想怎么拆。
  4. "嵌套调用和递归是一回事"——不是。嵌套是"A 调 B",递归是"A 调 A"。

⚠️ 必须记的一个坑:写嵌套调用时函数名别写错成自己——一旦某个函数体内直接调用了它自己,就变成了无限递归,程序会因栈溢出直接崩溃。编译器通常不报错,只在运行时炸,这就是 6.3.3 要专门讲的事。

自测三问(点开对答案) 1. 嵌套调用的执行顺序规律是什么?——先进后出:进入时一层层往里钻,返回时一层层往外返。 2. 为什么是这个顺序?——每次调用都在调用栈上记一笔,返回时必须按倒序撕掉。 3. 嵌套调用和递归的区别?——嵌套是"A 调 B",递归是"A 调 A"。

相关笔记