嵌套调用

一、嵌套调用的概念

C++ 允许函数进行嵌套调用。嵌套调用指的是:函数 A 在执行过程中调用了函数 B,函数 B 在执行过程中又调用了函数 C,以此类推,形成多层函数调用关系。

需要注意的是:嵌套调用不等同于递归。嵌套调用是不同函数之间的互相调用;递归是函数自己调用自己。

二、嵌套调用的执行流程

以”函数1调用函数2,函数2再调用函数3″为例:

  1. 程序从主函数开始执行。
  2. 主函数调用函数1,程序流程跳转到函数1。
  3. 函数1执行过程中调用函数2,程序流程跳转到函数2。
  4. 函数2执行过程中调用函数3,程序流程跳转到函数3。
  5. 函数3执行完毕,返回结果给函数2。
  6. 函数2继续执行后续语句,完毕后返回结果给函数1。
  7. 函数1继续执行后续语句,完毕后返回结果给主函数。
  8. 主函数继续执行,直到程序结束。

每一层函数调用都会在调用栈中压入一个新的栈帧,函数返回时弹出。嵌套层数过深可能导致栈溢出。

三、示例:求两个整数的平方和

需求:输入两个整数,求它们的平方和(x² + y²)。

思路:定义 fun1 用于求 x 的 n 次方,定义 fun2 调用 fun1 分别求 x² 和 y² 然后相加,主函数中调用 fun2 并输出结果。

#include <iostream>
using namespace std;

// fun1:求 x 的 n 次方
int fun1(int x, int n)
{
    int r = 1;
    while (n-- != 0)
    {
        r *= x;
    }
    return r;
}

// fun2:求 x² + y²,嵌套调用 fun1
int fun2(int x, int y)
{
    return fun1(x, 2) + fun1(y, 2);
}

int main()
{
    int x = 2;
    int y = 3;
    cout << "平方和 = " << fun2(x, y) << endl;   // 输出 13
    return 0;
}Code language: PHP (php)

分析:main 调用 fun2,fun2 内部两次调用 fun1 分别求 x² 和 y²,fun1 返回结果后 fun2 求和并返回,main 输出最终结果。

四、代码示例

以下代码演示了嵌套调用的更多应用场景:

#include <iostream>
using namespace std;

// 示例1:三层嵌套调用
int add(int a, int b)
{
    return a + b;
}

int multiply(int a, int b)
{
    return a * b;
}

int calculate(int x, int y, int z)
{
    int sum = add(x, y);          // 调用 add
    int result = multiply(sum, z); // 调用 multiply
    return result;
}

// 示例2:嵌套调用实现阶乘求和
int factorial(int n)
{
    int f = 1;
    for (int i = 1; i <= n; i++)
        f *= i;
    return f;
}

int sumOfFactorials(int n)
{
    int total = 0;
    for (int i = 1; i <= n; i++)
    {
        total += factorial(i);    // 循环内嵌套调用 factorial
    }
    return total;
}

// 示例3:嵌套调用判断素数并统计
bool isPrime(int n)
{
    if (n < 2) return false;
    for (int i = 2; i * i <= n; i++)
        if (n % i == 0) return false;
    return true;
}

int countPrimes(int a, int b)
{
    int count = 0;
    for (int i = a; i <= b; i++)
    {
        if (isPrime(i))           // 循环内嵌套调用 isPrime
            count++;
    }
    return count;
}

// 示例4:嵌套调用求最大公约数
int gcd(int a, int b)
{
    while (b != 0)
    {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}

int lcm(int a, int b)
{
    return a * b / gcd(a, b);     // 调用 gcd
}

// 示例5:多层嵌套(三层)
int square(int x)
{
    return x * x;
}

int sumOfSquares(int a, int b)
{
    return square(a) + square(b); // 调用 square
}

int complexCalc(int x, int y)
{
    int part1 = sumOfSquares(x, y); // 调用 sumOfSquares
    int part2 = square(x + y);      // 调用 square
    return part1 + part2;
}

int main()
{
    // 测试三层嵌套
    cout << "calculate(2, 3, 4) = " << calculate(2, 3, 4) << endl;

    // 测试阶乘求和
    cout << "1!+2!+3!+4!+5! = " << sumOfFactorials(5) << endl;

    // 测试素数统计
    cout << "10~50 之间的素数个数:" << countPrimes(10, 50) << endl;

    // 测试最大公约数和最小公倍数
    cout << "gcd(12, 18) = " << gcd(12, 18) << endl;
    cout << "lcm(12, 18) = " << lcm(12, 18) << endl;

    // 测试多层嵌套
    cout << "complexCalc(2, 3) = " << complexCalc(2, 3) << endl;

    return 0;
}Code language: PHP (php)

五、注意事项

  • 嵌套调用是 C++ 程序的基本组织方式,几乎所有实际程序都包含多层嵌套调用。
  • 每一层函数调用都会在栈上分配空间(栈帧),存储形参、局部变量和返回地址。嵌套层数过深可能导致栈溢出。
  • 嵌套调用中,被调函数执行完毕后自动返回调用点继续执行。如果某层函数提前 return,则逐层向上返回。
  • 函数之间可以相互调用,形成复杂的调用关系,但不允许函数嵌套定义(即在一个函数内部定义另一个函数)。
  • 合理设计函数接口和调用层次,可以使程序结构清晰、模块化程度高。

六、常见错误

1. 循环调用(间接递归)
int foo() { return bar(); }
int bar() { return foo(); }   // foo 和 bar 互相调用,无终止条件,导致栈溢出Code language: JavaScript (javascript)

如果确实需要互相调用,必须设置终止条件。

2. 忘记写函数原型声明
int main()
{
    foo();     // 错误:foo 未声明
    return 0;
}
int foo() { return bar(); }
int bar() { return 0; }Code language: JavaScript (javascript)

解决:在 main 之前添加 int foo(); int bar();。

3. 嵌套层数过深
int level1() { return level2(); }
int level2() { return level3(); }
// ... 一直嵌套到 level10000Code language: JavaScript (javascript)

可能导致栈溢出,应重构为循环或迭代方式。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注