第6.14章: 高阶函数
概述
高阶函数就是接受另一个函数作为参数,或者返回一个 函数的函数。你已经见过它的构件:函数指针与无捕获的 lambda。
在本章中,你将学到:
- 如何把函数传给其他函数
- 如何从函数返回函数
- 如何构建简单的分派系统
- 如何使用无捕获 lambda 作为回调
1. 把函数传给其他函数
函数指针形参让你能把行为传入一个函数。
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; }
println(operate(3, 4, add)); // 7
println(operate(3, 4, mul)); // 12
这是高阶函数最简单的形式。
2. 使用无捕获 lambda 作为回调
没有捕获的 lambda 可以用在任何期望函数指针的地方。
println(operate(3, 4, [](int a, int b) { return a - b; }));
这对快速的一次性操作很有用。
3. 从函数返回函数
函数可以返回函数指针。这让你能在运行时选择行为。
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int (*select_op(char c))(int, int)
{
if(c == '+') return add;
return sub;
}
auto op = select_op('+');
println(op(10, 3)); // 13
4. 简单的分派表
你可以把多个函数存入一个数组,并在运行时选择其中一个。
int add(int a, int b) { return a + b; }
int mul(int a, int b) { return a * b; }
int sub(int a, int b) { return a - b; }
int (*ops[3])(int, int){add, mul, sub};
println(ops[0](3, 4)); // add
println(ops[1](3, 4)); // mul
println(ops[2](3, 4)); // sub
这是解释器、状态机和命令分派器的基础。
5. 带参数的回调
回调就是传给另一个函数、以便稍后执行的函数。
void repeat(int n, void (*f)())
{
for(int i{}; i != n; ++i)
f();
}
repeat(3, [] { println("tick"); });
这会打印三次 tick。
要点
- 高阶函数接受函数或返回函数。
- 函数指针让你能把行为传入函数。
- 无捕获 lambda 可以用作函数指针。
- 返回函数指针可在运行时选择行为。
- 分派表可实现简单的解释器与状态机。