第6.12章: 函数指针
概述
函数指针是指向函数而不是数据的指针。 函数指针让你能够:
- 间接调用函数
- 把函数传给其他函数
- 把函数存入数组或表
- 在运行时选择行为
- 与 C API 交互
在本章中,你将学到函数指针如何工作、如何声明它们、如何调用它们,
以及如何使用 ::fast_io::funcvw() 操纵器打印它们的地址。
1. 函数类型
函数根据其参数列表和返回类型而具有一个类型。
int add(int a, int b);
add 的类型是:
int(int, int)
这表示:“一个接受两个 int 并返回 int 的函数。”
2. 函数会退化为指针
正如数组会退化为指针一样,函数名也会退化为指向该函数的 指针。
int add(int a, int b)
{
return a + b;
}
int (*p)(int, int) = add; // function pointer
p 的类型是“指向接受两个 int 并返回 int 的函数的
指针”。
3. 通过函数指针调用
你可以像调用普通函数一样调用函数指针。
int result = p(3, 4); // calls add(3, 4)
也可以写成:
int result = (*p)(3, 4); // equivalent
4. 把函数指针传给函数
函数指针可以用作参数类型。
int operate(int a, int b, int (*op)(int, int))
{
return op(a, b);
}
用法:
int add(int a, int b) { return a + b; }
int mul(int a, int b) { return a * b; }
::fast_io::io::println(operate(3, 4, add)); // 7
::fast_io::io::println(operate(3, 4, mul)); // 12
5. 用 using 别名提升清晰度
函数指针的语法很冗长。你可以用 using 别名来简化它。
using binary_op = int(*)(int, int);
int operate(int a, int b, binary_op op)
{
return op(a, b);
}
这让代码更易读、更易维护。
6. 返回函数指针
函数可以返回函数指针。
binary_op choose(bool multiply)
{
if(multiply)
return mul;
return add;
}
用法:
auto f = choose(true);
::fast_io::io::println(f(3, 4)); // 12
7. 函数指针数组
你可以把多个函数存入一个数组。
binary_op ops[2]{add, mul};
::fast_io::io::println(ops[0](3, 4)); // add
::fast_io::io::println(ops[1](3, 4)); // mul
这对跳转表、解释器和分派系统很有用。
8. 用 ::fast_io::funcvw() 打印函数地址
fast_io 库提供了一个名为 funcvw() 的特殊操纵器,
用来打印函数或函数指针的地址。这在调试、教学,
以及验证两个函数指针是否指向同一函数时极其有用。
示例:打印函数的地址
int add(int a, int b) { return a + b; }
println(funcvw(add));
这会打印 add 函数的地址。
示例:打印函数指针的地址
int (*p)(int, int) = add;
println(funcvw(p));
这会打印 p 中存储的地址。它应当与为 add
打印的地址相同。
funcvw() 适用于:
- 函数名(会退化为指针)
- 函数指针变量
- 函数指针数组
9. 函数指针为何重要
函数指针在以下领域不可或缺:
- 底层 C 与 C++ API
- 基于回调的库
- 信号处理程序
- 插件系统
- 解释器与虚拟机
- 性能关键代码中的跳转表
它们也是更高级特性的基础,例如:
要点
- 函数有类型,函数名会退化为指针。
- 函数指针允许间接调用函数。
- 你可以把函数指针传给函数,也可以返回它。
using别名让函数指针语法变得可控。::fast_io::funcvw()打印函数地址,用于调试。