CC++ & Algorithm

C++函数的定义与声明

困难83
语言版本:C++Python
概述:把重复的代码打包成“小积木”,随时可以搭到程序里。

把重复代码打包成积木:C++函数的定义与声明

同学们,写程序时经常会遇到“同样的事要做很多次”的情况。比如,要计算3的平方、8的平方、15的平方……每次都得写 3*38*815*15,既麻烦又容易写错。C++里有一种很聪明的办法——函数。它就像一块万能小积木,你把要做的事情提前做好,后面随时可以把它“搭”到程序里,只需要给积木不同的数据,它就能帮你算出结果。

函数不仅能让程序变短,还能让你的代码像搭乐高一样模块化:每一块积木负责一个独立的功能,出了问题只需要检查那块积木,其他部分不用动。


1. 函数是什么?——像“调料包”一样方便

想象一下,你在学校食堂吃面条,每次都想要加一点辣椒油。如果食堂阿姨把辣椒油放在一个大桶里,每次都要用勺子舀,很慢。更好的办法是:提前把辣椒油装成一个个小包(调料包)。想吃的时候,撕开一包倒进去就完了。

函数就是这样的“调料包”。它把一段能完成特定任务的代码包装起来,起一个名字(比如 addsquare)。以后你需要执行这个任务时,只需要“叫”它的名字,再给它一些必要的原料(参数),它就会自动完成工作,并把结果(返回值)还给你。


2. 如何制作一块“积木”——函数的定义

要制作一块积木,你需要告诉C++四件事:

  • 返回值类型:积木做完事之后,要给你一个什么东西?是整数(int)、小数(double)还是什么都不给(void)?
  • 函数名:积木的名字,比如 squaremaxNum,要让人一看就懂。
  • 参数列表:积木需要你提供哪些原料?写在括号里,每个原料都要说明类型和名字。
  • 函数体:积木具体怎么做事的代码,放在花括号 {} 里。

下面是一个计算任意整数平方的函数定义:

int square(int x) {      // 返回整数类型,函数名叫square,需要一个整数参数x
    return x * x;        // 计算x*x并返回结果
}

如果你想计算两个数中的最大值,可以再做一个积木:

int maxNum(int a, int b) {  // 返回整数,需要两个整数a和b
    if (a > b) {
        return a;           // 如果a大就返回a
    } else {
        return b;           // 否则返回b
    }
}

生活例子:你有一个零钱罐,里面有很多1元、5角、1角的硬币。你想知道一共有多少钱(单位是角)。你可以写一个函数 calcTotal,它接收三种硬币的数量,返回总钱数(角)。这样每次你数完硬币,只要调用这个函数,输入数字,就能立刻得到总钱数,不用自己加来加去。


3. 给积木贴一张“标签”——函数的声明

有时候,你的积木定义在程序中比较靠后的位置,但前面的代码想提前使用它。怎么办?你可以在程序最开始的地方贴一张“标签”,告诉C++:“我这里有这么一块积木,名叫square,它需要一个整数,返回一个整数,具体做法在后面写。”这个标签就是函数声明

声明很像函数的“抬头”,但不写具体怎么实现(没有花括号),只写返回类型、函数名和参数,最后跟一个分号。

int square(int x);   // 声明:我说有这个函数,但具体怎么做在后面再写

在大型项目里,声明通常放在文件开头或者一个单独的头文件.h 文件)里,这样程序里所有地方都能知道这块积木的存在。定义则放在另一个文件(.cpp 文件)里,实现具体功能。

声明只负责“说”(告诉编译器有这个函数),定义负责“做”(实际写出代码)。

如果没有定义就调用函数,编译器会报错“未定义的引用”,就像你找同学借一本《哈利·波特》,他说“我有这本书”,结果你去找时,发现他根本就没有书,你会很生气。


4. 新手容易掉进的“坑”

  1. 忘记写返回值:函数有返回类型(比如 int),就必须在函数体里写 return。否则程序不知道要给你什么结果。
    ❌ 错误:

    int plusOne(int x) {
        x + 1;       // 没写return,编译器会报错
    }
    

    ✅ 正确:

    int plusOne(int x) {
        return x + 1;   // 返回结果
    }
    
  2. 参数数量或类型不对:定义时写明了要两个 double,调用时却只给一个整数,或者给了三个整数,编译器会报错“没有匹配的函数”。

  3. 声明和定义不一致:比如声明里参数是 int,定义里却变成 double,编译器会认为它们是两个不同的函数,导致莫名其妙的问题。

  4. 忘记写分号:声明末尾一定要有分号 ;,定义的花括号后面不用分号。


5. 完整示例:用函数计算圆的面积和周长

下面是一个完整的程序,包含函数的声明、定义和调用。注意看代码中的中文注释,帮你理解每一行在干什么。

#include <iostream>
using namespace std;

// 函数的声明(贴在前面,告诉编译器有两个函数要用)
double circleArea(double r);       // 计算圆面积,参数r是半径,返回double
double circlePerimeter(double r);  // 计算圆周长

int main() {
    double radius;                 // 半径
    cout << "请输入圆的半径:";
    cin >> radius;
    
    double area = circleArea(radius);          // 调用函数,把radius传进去,得到面积
    double perimeter = circlePerimeter(radius); // 调用函数,得到周长
    
    cout << "面积 = " << area << endl;
    cout << "周长 = " << perimeter << endl;
    
    return 0;
}

// 函数的定义(实现具体功能)
double circleArea(double r) {              // 返回类型double,参数r
    const double pi = 3.1415926;           // 圆周率常量
    return pi * r * r;                     // 圆的面积公式
}

double circlePerimeter(double r) {         // 返回类型double,参数r
    const double pi = 3.1415926;
    return 2 * pi * r;                     // 圆的周长公式
}

你可以试着输入不同的半径,程序会正确输出面积和周长。如果想把函数定义直接写在 main 前面,那就不需要声明了,因为定义本身就包含了声明的作用。


6. 接下来还可以学什么?

函数是C++里最重要的积木块之一。掌握了它之后,还可以继续探索:

  • 函数重载:同一个函数名,可以有不同的参数版本(比如一个 sum 函数既能加两个整数,也能加三个整数)。
  • 递归:函数自己调用自己,解决像“爬楼梯”、“阶乘”这类问题。
  • 默认参数:给参数设一个默认值,调用时可以少写一个参数。
  • 头文件与多文件编程:把声明放在 .h 文件,定义放在 .cpp 文件,让代码组织更清晰。

现在,去试试自己写几个小函数吧!比如计算考试平均分、判断一个数是不是质数,或者模拟一个简易计算器。每写一个函数,你就搭起了一块属于自己的编程积木。

例题精讲

1单选题

关于C++中函数的声明与定义,以下说法正确的是?

A函数的声明和定义必须在同一个文件中
B同一个函数可以多次声明,但只能定义一次
C函数的定义可以省略返回类型,默认返回int
D函数声明时必须提供函数体
2判断题

在C++中,如果函数定义出现在函数调用之后,必须在调用前先声明该函数。

3填空题
补全以下函数定义,使其与函数声明匹配,功能为计算两个整数的差并返回。\n函数声明:int subtract(int a, int b);\n函数定义:___ subtract(int a, int b) { ___ a - b; }
4单选题

关于C++函数的默认参数,下列哪项描述是正确的?

A默认参数可以从左到右依次设置,无需连续
B默认参数必须在函数声明或定义中之一给出,不能同时指定
C默认参数只能用于最后一个参数
D在同一个作用域中,默认参数可以在后续声明中补充
5填空题
下列代码试图通过函数重载实现打印不同类型数据的功能,请补全函数定义。\n函数声明(重载):\nvoid print(int x);\nvoid print(double y);\n函数定义(第一个):void print(int x) { cout << "Integer: " << x << endl; }\n函数定义(第二个):___ print(___ y) { cout << "Double: " << y << endl; }