函数跳转表是把函数指针和数组结合在一起的应用方式,它充分利用数组的下标索引和函数指针的自动跳转功能,实现用户输入和功能函数的自动关联。比如一个软件计算器,用户输入两个数(op1/op2)和一个操作代号(oper),代码根据约定的代号/操作映射关系,决定调用哪种运算。常规实现方式为:
switch(oper)
{
case ADD: result=add(op1,op2);break;
case SUB: result=sub(op1,op2);break;
case MUL: result=mul(op1,op2);break;
case DIV: result=div(op1,op2);break;
......
}
这里用函数而不直接用加减乘除运算符只是举例,另外把具体操作独立出来也是一种良好的设计思想,且后面扩展诸如指数/三角函数等运算必须用独立函数实现。
上面方式可实现简单加减乘除计算,但功能完善的计算器需要上百种运算,这时switch语句会非常长,一条条重复显得过于僵化。能不能用更简单的方法实现?
考虑到操作代号是整数,如果约定所有操作代号值从零开始递增排列,就形成数组下标,于是可以用函数指针跳转表来实现。方法是:先声明一系列功能函数,然后按照操作代号依次用相应函数初始化,建立一个函数指针数组,如:
int add(int, int); int sub(int, int); int mul(int, int); int div(int, int);
int (*oper_func[])(int, int)={add,sub,mul,div,...};
数组初始化时,从下标0开始逐一用某操作代码映射相应计算函数,设ADD为0,SUB是1,以此类推。初始化后,就能用一条语句替换整个switch模块,即:result=oper_func[oper](op1,op2);通过oper从函数指针数组中选择正确的函数指针并调用,完成相应功能。
这里推荐大家了解—下中断向量的概念,它实际也使用了函数跳转表思想。而更进一步还可把函数指针数组扩展为映射函数指针的哈希表(自查hash),以更灵活的在用户输入与函数指针集合间建立映射。此外函数跳转表也是“有限状态机”的基础。
这里简单展示了跳转表技巧,比这个技巧本身更重要的是,可以借此换个视角加深对函数指针的理解。就象旅游并不只为拍一堆漂亮照片,扩展视野体味人生才是更深层价值所在。技术也有思想和深度,也需要积累思考和感悟。