C++ 函数指针(Function Pointer)详解
函数指针是指向函数的指针,它可以存储函数地址,并通过该指针调用函数。函数指针在回调函数、策略模式、动态函数调用等场景中非常有用。
1. 什么是函数指针?
函数指针是一个指向函数的指针,它存储的是函数的地址,并允许通过指针调用该函数。
📌 语法
返回类型 (*函数指针名)(参数列表);
2. 基本示例
(1)定义和使用函数指针
#include <iostream>
// 普通函数
void hello() {
std::cout << "Hello, Function Pointer!" << std::endl;
}
int main() {
void (*funcPtr)(); // ✅ 定义函数指针
funcPtr = hello; // ✅ 让指针指向 `hello` 函数
funcPtr(); // ✅ 通过指针调用函数
return 0;
}
📌 输出
Hello, Function Pointer!
✅ funcPtr
存储 hello
函数地址,并通过 funcPtr()
调用它。
3. 带参数和返回值的函数指针
#include <iostream>
// 带参数和返回值的函数
int add(int a, int b) {
return a + b;
}
int main() {
int (*funcPtr)(int, int); // ✅ 定义函数指针
funcPtr = add; // ✅ 让指针指向 `add`
std::cout << funcPtr(3, 5) << std::endl; // ✅ 通过指针调用 `add(3, 5)`
return 0;
}
📌 输出
8
✅ funcPtr
存储 add()
地址,调用 funcPtr(3, 5)
计算 3 + 5
。
4. 函数指针作为函数参数
函数指针可以作为回调函数,在函数内部调用:
#include <iostream>
// 定义回调函数类型
void process(int a, int b, int (*op)(int, int)) {
std::cout << "Result: " << op(a, b) << std::endl;
}
// 具体实现
int add(int x, int y) { return x + y; }
int multiply(int x, int y) { return x * y; }
int main() {
process(3, 5, add); // ✅ 传递 `add` 函数
process(3, 5, multiply); // ✅ 传递 `multiply` 函数
return 0;
}
📌 输出
Result: 8
Result: 15
✅ process(3, 5, add)
让 op
绑定到 add()
,支持动态调用!
5. 使用 typedef
或 using
简化函数指针
函数指针的语法比较复杂,可以使用 typedef
或 using
来简化。
(1)使用 typedef
typedef int (*FuncPtr)(int, int); // ✅ 定义函数指针类型
int subtract(int a, int b) { return a - b; }
int main() {
FuncPtr ptr = subtract; // ✅ 使用 `FuncPtr`
std::cout << ptr(10, 3) << std::endl;
}
(2)使用 using
(C++11)
using FuncPtr = int (*)(int, int); // ✅ 定义函数指针类型(C++11)
int subtract(int a, int b) { return a - b; }
int main() {
FuncPtr ptr = subtract; // ✅ 使用 `FuncPtr`
std::cout << ptr(10, 3) << std::endl;
}
✅ typedef
和 using
让代码更简洁!
6. 函数指针数组
函数指针可以组成数组,实现动态选择函数:
#include <iostream>
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int main() {
int (*operations[3])(int, int) = { add, subtract, multiply }; // ✅ 函数指针数组
std::cout << operations[0](3, 4) << std::endl; // 3 + 4 = 7
std::cout << operations[1](7, 2) << std::endl; // 7 - 2 = 5
std::cout << operations[2](3, 3) << std::endl; // 3 * 3 = 9
}
📌 输出
7
5
9
✅ 使用索引动态调用不同函数,提高灵活性!
7. C++11 std::function
(更现代的方式)
C++11 提供了 std::function
作为函数指针的现代替代,它支持Lambda 表达式、成员函数、绑定参数等:
#include <iostream>
#include <functional> // ✅ 引入 `std::function`
int add(int a, int b) { return a + b; }
int main() {
std::function<int(int, int)> func = add; // ✅ 绑定普通函数
std::cout << func(3, 5) << std::endl; // ✅ 运行
}
✅ std::function
允许存储更复杂的调用目标,如 Lambda
和成员函数!
8. 结论
功能 | 函数指针 | **std::function (C++11+) |
---|---|---|
存储普通函数 | ✅ 支持 | ✅ 支持 |
存储 Lambda | ❌ 不支持 | ✅ 支持 |
存储成员函数 | ❌ 复杂 | ✅ 方便 |
类型安全 | ❌ 可能出错 | ✅ 更安全 |
适用场景 | 轻量级回调 | 泛型函数封装 |
🚀 推荐:C++11 及以上,使用 std::function
代替传统函数指针! 🚀
是的,typedef
在 C++ 中的作用是 给已有类型取别名,但在函数指针的场景中,它可以让复杂的函数指针声明变得更易读和使用。
1. 为什么 typedef
可以用于函数指针?
函数指针的标准声明可能会很复杂,例如:
int (*funcPtr)(int, int);
这意味着 funcPtr
是一个指针,指向一个接受两个 int
参数并返回 int
的函数。
如果我们要在多个地方使用这个函数指针类型,每次都要写 int (*)(int, int)
,这既冗长又容易出错。使用 typedef
让它更清晰:
typedef int (*FuncPtr)(int, int);
这表示:
FuncPtr
是一个新的类型别名,它等价于int (*)(int, int)
。- 现在,我们可以直接使用
FuncPtr
来定义函数指针:FuncPtr ptr; // 等价于 int (*ptr)(int, int);
2. typedef
在函数指针中的使用
✅ 使用 typedef
简化函数指针
#include <iostream>
typedef int (*FuncPtr)(int, int); // ✅ 定义函数指针类型别名
int add(int a, int b) { return a + b; }
int main() {
FuncPtr ptr = add; // ✅ `ptr` 现在是一个函数指针
std::cout << ptr(3, 5) << std::endl; // ✅ 调用 `add(3, 5)`
}
📌 输出
8
✅ FuncPtr
让 ptr
变得易读,等价于 int (*ptr)(int, int);
。
3. typedef
用于函数指针数组
函数指针数组允许存储多个函数,并动态选择不同的函数执行:
typedef int (*FuncPtr)(int, int); // ✅ 定义函数指针别名
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int main() {
FuncPtr operations[] = { add, subtract }; // ✅ 函数指针数组
std::cout << operations[0](5, 3) << std::endl; // ✅ add(5, 3)
std::cout << operations[1](5, 3) << std::endl; // ✅ subtract(5, 3)
}
📌 输出
8
2
✅ operations[0]
选择 add()
,operations[1]
选择 subtract()
。
4. C++11 using
替代 typedef
C++11 提供了 using
作为 typedef
的更现代的替代:
using FuncPtr = int (*)(int, int); // ✅ C++11 写法
与 typedef
等价,但语法更直观:
FuncPtr ptr = add;
🚀 推荐使用 using
,可读性更强!
5. 结论
功能 | typedef 方式 | using 方式(C++11) |
---|---|---|
定义函数指针别名 | typedef int (*FuncPtr)(int, int); | using FuncPtr = int (*)(int, int); |
定义函数指针数组 | FuncPtr arr[2]; | FuncPtr arr[2]; |
可读性 | ⭐⭐⭐ | ⭐⭐⭐⭐(更直观) |
推荐度 | ✅ 传统 C++ 适用 | ✅ 现代 C++ 推荐 |
✅ typedef
可以给复杂类型(如函数指针)取别名,提升可读性,但在 C++11 及以上,推荐使用 using
替代 typedef
! 🚀