C++的表驱动法
Posted Zhou2021
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++的表驱动法相关的知识,希望对你有一定的参考价值。
目的:使用表驱动法,替换复杂的if/else和switch/case语句。
一、常用示例
以switch为例,常用示例如下:
Funcition()
{
switch (key)
{
case key1:
statements 1;
break;
case key2:
statements 2;
break;
...
case keyn:
statements n;
break;
default:
break;
}
}
上述switch代码段,实际集成了3种类型逻辑:
1. 实现关键字的处理代码;
2. 将关键字与处理代码关联;
3. 以关键字选择分支,执行处理代码;
我们将在一个switch代码中维护3种变化。将1的处理代码段,模块化为函数后,变化点减少为2个。
在分支增加到几十个时,代码维护性变得很差;而且switch对非整数类型无能为力。
二、表驱动法
做法:
1. 将变化点2,做成一个[关键字:处理函数]映射结构(推荐map容器),在独立函数中赋值。
2. 将变化点3,做成一个查找关键字,执行对应函数的简单函数。
好处:
1. 独立出“选择分支”变化点,变为固定的处理流程。
2. 独立出“关键字和处理函数的关联”,易于维护。
限制条件:
1. 处理函数类型一样(这在C++中不成问题);
2. 处理函数简单,但每个函数有差异(如果处理较为复杂,请使用创建型设计模式)
扩展:
1. 对于处理函数由符合条件分支情况,变化点2使用list结构,按优先级关联处理函数,使用 “职责链”形式的表驱动法。
三、C++实现注意
代码:
参见 C++表驱动法代码示例。
关注点:
主要关注3个点,维护第2、3点
1. HandleKeyword(),根据关键字,执行处理函数。固定后基本不改变;
2. MapKeyToHandle(),关联关键字到处理函数;
3. Handle(),各个处理函数
成员函数指针使用注意
1. 声明格式,与C相比,函数指针前要包含类域;
typedef bool (TableDrive:: *PHandle)();
2. 声明位置,包含在类中,否则不能识别类域标志;
3. 赋值语法格式,与C相比,函数指针前要包含类域;
PHandle pFunction = &TableDrive::HandleKeyA;
4. 调用语法格式,与C相比,需要加上this,并以强制解引用方式调用;
(this->*pFunction)();
四、实用案例
1. 菜单调节。一个模块,有几十个菜单参数可以调节,每个菜单调节的步进、范围不同,但都是“触发消息、调节数值”流程。
2. 按键响应。多个按键,属于“按键,执行对应处理函数”流程。
3. 鼠标操控。不同状态下移动鼠标,属于“状态判断、响应鼠标处理函数”流程。
参考资料
1. 《代码大全》(第2版)中文版,第18章 表驱动法。
以上是关于C++的表驱动法的主要内容,如果未能解决你的问题,请参考以下文章