一、引言:从 "写代码" 到 "设计程序"
在前面三篇文章中,我们已经掌握了 C++ 的基础语法、数据类型、变量、表达式以及最核心的分支与循环。我们已经能够写出具备逻辑判断、循环执行、数据计算能力的程序,比如判断成绩、计算累加、打印图形等。
但随着程序功能越来越多,代码会迅速膨胀:
- 所有逻辑都堆在 main 函数里;
- 相同功能的代码反复复制粘贴;
- 代码行数上千行后,阅读困难、修改困难、排查错误更困难;
- 无法在多个项目中复用已有功能。
为了解决这些问题,编程语言提供了 ** 函数(Function)** 机制。
函数是 C++ 模块化编程的基石。 它的作用是:
- 封装重复代码,避免冗余;
- 拆分复杂逻辑,让程序结构清晰;
- 实现代码复用,一次编写,多处调用;
- 便于团队协作,每人负责不同函数模块。
可以说: 不会使用函数,就只能写 "小脚本"; 学会函数,才能真正开发结构化、可维护、可扩展的程序。
本篇文章将全面、系统、深入讲解 C++ 函数的全部核心知识点,内容包括:
- 函数的定义、声明、调用;
- 函数参数:形参、实参、值传递;
- 函数返回值:return、void;
- 函数重载(C++ 重要特性);
- 默认参数;
- 内联函数;
- 递归函数;
- 多文件编程与头文件;
- 函数的常见错误与工程规范。
学完本篇,你将正式进入模块化程序设计的世界。
二、什么是函数
函数是完成特定功能的、可重复调用的代码块 。 一个完整的 C++ 程序由一个 main 函数 + 若干其他函数组成。
main 是程序入口,其他函数由 main 直接或间接调用。
函数的意义
- 把大问题拆成小问题
- 把复杂逻辑拆成简单逻辑
- 代码可复用
- 易读、易改、易调试
- 适合大型项目开发
三、函数的定义与调用
(一)函数定义语法
cpp
运行
返回值类型 函数名(参数列表)
{
函数体;
return 返回值;
}
五部分:
- 返回值类型:函数执行完后返回的数据类型(无返回值用 void)。
- 函数名:见名知意,命名规则同变量。
- 参数列表:调用时传入的数据(0 个或多个)。
- 函数体:具体执行代码。
- return:返回结果并结束函数。
(二)最简单的函数示例
cpp
运行
// 定义:打印Hello
void sayHello()
{
cout << "Hello, Function!" << endl;
}
(三)函数调用
函数必须被调用才会执行。 调用方式:
cpp
运行
函数名(参数);
完整示例:
cpp
运行
#include <iostream>
using namespace std;
void sayHello() {
cout << "Hello, Function!" << endl;
}
int main() {
sayHello(); // 调用函数
return 0;
}
四、带参数的函数
函数可以接收外部传入的数据,称为参数。
- 形参(形式参数):定义函数时写的参数。
- 实参(实际参数):调用函数时传的值。
示例:求两个整数的最大值
cpp
运行
int max(int a, int b) {
return a > b ? a : b;
}
int main() {
int m = max(10, 20); // 10、20是实参
cout << m << endl;
return 0;
}
C++ 默认是值传递
调用函数时,实参的值被复制给形参 。 函数内部修改形参,不会影响外面的实参。
示例:
cpp
运行
void change(int x) {
x = 100;
}
int main() {
int a = 10;
change(a);
cout << a; // 仍然是10
return 0;
}
五、带返回值的函数
返回值是函数执行后给调用者的结果。
规则:
- 返回类型不是 void,必须写 return;
- return 只能返回一个值;
- return 执行后,函数立即结束。
示例:求立方
cpp
运行
int cube(int n) {
return n * n * n;
}
无返回值函数用 void:
cpp
运行
void print(int n) {
cout << n << endl;
}
六、函数声明(最重要知识点之一)
C++ 编译器是从上到下编译的。 如果函数定义在 main 之后,编译器找不到函数,会报错。
解决方法:函数声明。
声明格式:
cpp
运行
返回值类型 函数名(参数列表);
示例:
cpp
运行
#include <iostream>
using namespace std;
// 函数声明
int add(int a, int b);
int main() {
cout << add(3, 5);
return 0;
}
// 函数定义
int add(int a, int b) {
return a + b;
}
声明就像 "告诉编译器:这个函数后面会出现,请先放行"。
七、函数重载(C++ 核心特性)
C++ 允许多个函数同名,但参数不同 ,这就是函数重载。
重载条件:
- 函数名相同
- 参数个数、类型、顺序不同
- 返回值不同不能构成重载
示例:
cpp
运行
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
调用时,编译器会根据传入参数自动匹配正确函数。
重载的意义:统一功能命名,方便使用。 例如:
- printInt(int)
- printDouble (double) 可以统一写成 print,由编译器自动区分。
八、默认参数
C++ 允许给参数指定默认值。 调用时如果不传该参数,自动使用默认值。
示例:
cpp
运行
void show(string msg = "Hello") {
cout << msg << endl;
}
int main() {
show(); // 输出 Hello
show("Hi"); // 输出 Hi
return 0;
}
规则:
- 默认参数必须靠右;
- 声明时写默认值,定义时不要重复写。
九、内联函数(inline)
用 inline 声明的函数叫内联函数 。 作用:在编译时将函数代码直接展开到调用位置,减少函数调用开销。
适合:函数体很短、被频繁调用的函数。
cpp
运行
inline int square(int x) {
return x * x;
}
注意:
- 递归函数不能内联;
- 函数体太长不适合内联。
十、递归函数
函数调用自己,称为递归。
递归必须满足两个条件:
- 基线条件(退出条件):不再递归;
- 递归条件:把问题规模缩小。
示例:求阶乘 n!
cpp
运行
int fact(int n) {
if (n == 1) return 1; // 基线条件
return n * fact(n - 1); // 递归
}
执行过程: fact (5) → 5fact(4) → 5 4fact(3) → ... → 5 432*1
经典递归案例:
- 斐波那契数列
- 汉诺塔
- 二叉树遍历
- 快速排序
十一、函数的典型应用案例
案例 1:判断素数函数
cpp
运行
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;
}
案例 2:求数组最大值
cpp
运行
int maxArray(int arr[], int len) {
int m = arr[0];
for (int i = 1; i < len; i++) {
if (arr[i] > m) m = arr[i];
}
return m;
}
案例 3:递归求斐波那契
cpp
运行
int fib(int n) {
if (n == 1 || n == 2) return 1;
return fib(n - 1) + fib(n - 2);
}
十二、多文件编程(模块化工程)
真正的 C++ 项目不会把所有代码写在一个文件里。
标准结构:
- .h 头文件:函数声明、结构体、类声明
- .cpp 源文件:函数实现
示例: math.h
cpp
运行
#pragma once
int add(int a, int b);
math.cpp
cpp
运行
#include "math.h"
int add(int a, int b) {
return a + b;
}
main.cpp
cpp
运行
#include "math.h"
int main() {
add(3,5);
return 0;
}
优点:
- 代码结构清晰
- 多人协作不冲突
- 便于维护和升级
- 可复用模块
十三、函数常见错误(新手必看)
1. 函数调用时写错名字
cpp
运行
add(2,3); →写成 ad(2,3);
2. 函数定义在 main 后面,又没有声明
报错:标识符未找到
3. 有返回值函数忘记 return
cpp
运行
int add(int a,int b) {
int c = a + b;
// 没return
}
4. 形参和实参类型不匹配
cpp
运行
int f(int a);
调用:f(3.14);
5. 递归没有退出条件 → 栈溢出、程序崩溃
cpp
运行
void f() { f(); }
6. 重载只靠返回值不同 → 编译失败
cpp
运行
int f();
void f();
错误!
7. 默认参数放在左边
cpp
运行
void f(int a=10, int b); 错误!
十四、函数编程规范(工程级)
- 一个函数只做一件事;
- 函数名见名知意:getMax、isPrime、calculate;
- 函数长度不宜过长(最好不超过 50 行);
- 参数不超过 4 个;
- 先声明,后调用;
- 多文件项目必须分 .h 和 .cpp;
- 避免过度递归;
- 注释说明函数功能、参数、返回值。
十五、本章总结
本篇文章系统、完整、深入讲解了 C++函数全部核心内容,是模块化编程的基石:
- 函数定义、调用、声明;
- 参数传递:形参、实参、值传递;
- 返回值:return、void;
- 函数重载(C++ 重要特性);
- 默认参数、内联函数;
- 递归函数;
- 多文件编程;
- 常见错误与工程规范。
掌握函数,意味着你已经从 "写代码的人" 升级为 "设计程序的人"。 你可以:
- 拆分复杂项目
- 封装工具函数
- 实现代码复用
- 参与多人协作开发
- 写出结构清晰、可维护的高质量 C++ 代码
函数是 C++ 从基础走向进阶的分水岭。 学好函数,后面的数组、指针、结构体、类、STL 都会变得非常容易。
下一篇预告
第 5 篇《C++ 指针与引用:底层内存访问核心》(4000 字以上) 指针是 C++ 最强大、最核心、最难的部分,也是区分普通程序员和高级程序员的关键。