函数指针
函数指针指向函数地址,可通过它调用函数,实现回调和动态绑定。
函数指针
函数指针
函数指针是 C++ 中一种保存函数地址的指针变量,允许像调用普通函数那样通过指针调用函数。它是理解回调机制、策略模式、以及 C/C++ 中函数灵活性的基础。
基本定义格式
1
返回类型 (*函数指针名)(参数类型列表);
示例:
1
2
3
4
5
6
7
8
9
10
11
12
int add(int a, int b) {
return a + b;
}
// 定义函数指针
int (*funcPtr)(int, int);
// 把函数地址赋给指针
funcPtr = add;
// 通过指针调用函数
int result = funcPtr(3, 4); // 结果是 7
经典用途
回调函数(如排序比较器):
1
2
3
4
5
6
7
8
9
10
bool cmp(int a, int b) {
return a > b;
}
void sort(int* arr, int n, bool (*cmpFunc)(int, int)) {
for (int i = 0; i < n - 1; ++i)
for (int j = i + 1; j < n; ++j)
if (!cmpFunc(arr[i], arr[j]))
std::swap(arr[i], arr[j]);
}
调用:
1
2
int arr[] = {3, 1, 5, 2};
sort(arr, 4, cmp); // 使用 cmp 作为比较器
简化语法(使用 typedef
或 using
)
- 使用 typedef:
1
2
typedef int (*CalcFunc)(int, int);
CalcFunc f = add;
- 使用 using(推荐):
1
2
using CalcFunc = int(*)(int, int);
CalcFunc f = add;
函数指针数组(策略表)
1
2
3
4
5
6
7
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
using CalcFunc = int(*)(int, int);
CalcFunc ops[] = {add, sub};
int result = ops[0](10, 5); // 调用 add,结果是 15
对比 lambda、std::function、虚函数指针
特性/维度 | 函数指针 | Lambda | std::function | 虚函数指针(多态) |
---|---|---|---|---|
🧠 类型安全 | ✅ 有 | ✅ 有 | ✅ 有 | ✅ 有 |
📦 可捕获变量(闭包) | ❌ 不支持 | ✅ 支持(捕获) | ✅ 支持捕获 | ❌ 不支持 |
🔁 运行时可替换性 | ✅ | ✅/⚠️(无捕获) | ✅ 支持 | ✅ 支持 |
🧮 调用开销(性能) | 🚀 极快(等同函数调用) | 🚀 极快(无捕获) | 🐢 慢些(封装、堆分配) | 🚀 快(虚表指针跳转) |
🛠️ 存储/语法复杂度 | 中(函数签名繁琐) | 简洁 | 简洁 | 中(需要类定义) |
🧩 可用于类成员 | ⚠️ 不能直接 | ✅ 可 | ✅ 可 | ✅ 虚函数 |
♻️ 可用于策略/回调 | ✅ 是 | ✅ 是 | ✅ 是 | ✅ 是 |
🧱 是否编译期可求值 | ❌ 否 | ⚠️ 无捕获可以 | ❌ 否 | ❌ 否 |
函数指针(最古老也最快)
1
2
3
int add(int a, int b) { return a + b; }
int (*fptr)(int, int) = add;
fptr(3, 4); // 结果 7
- 优点:开销低、语义清晰
- 缺点:不能绑定状态、不支持捕获、不支持类成员函数
Lambda 表达式
1
2
3
4
5
auto f = [](int a, int b) { return a + b; };
f(3, 4); // 结果 7
int x = 10;
auto g = [x](int y) { return x + y; }; // 捕获外部变量
- 有状态时是类对象(编译器生成),不能隐式转函数指针
- 无捕获时可以自动转成函数指针
std::function
(泛型可调用封装器)
1
2
3
4
5
6
#include <functional>
std::function<int(int, int)> f = [](int a, int b) {
return a + b;
};
f(3, 4); // 结果 7
- 支持 lambda(有/无捕获)、函数指针、成员函数、仿函数
- 内部封装复杂类型,易用但可能有堆内存开销
- 推荐用于高抽象、插件系统、通用回调接口
虚函数指针(多态)
1
2
3
4
5
6
7
8
9
10
class Strategy {
public:
virtual int apply(int a, int b) = 0;
virtual ~Strategy() = default;
};
class Add : public Strategy {
public:
int apply(int a, int b) override { return a + b; }
};
- 支持接口多态(运行时绑定)
- 类中通过虚函数表调用,支持成员状态
- 有轻微开销(虚表指针跳转),但是面向对象设计核心
场景 | 推荐方案 | 理由 |
---|---|---|
高性能、无状态策略(如 sort) | ✅ 函数指针 / 无捕获 Lambda | 快,简单 |
动态策略,有捕获 | ✅ std::function | 支持闭包 |
面向对象策略,多态结构 | ✅ 虚函数 | 扩展性强 |
编译期策略 | ✅ 模板 / constexpr 函数 | 编译时计算 |
小工具函数 / callback | ✅ Lambda | 简洁、现代 |
本文由作者按照 CC BY 4.0 进行授权