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++的表驱动法的主要内容,如果未能解决你的问题,请参考以下文章

C语言表驱动法编程实践(精华帖,建议收藏并实践)

这些 C++ 代码片段有啥作用?

有趣的 C++ 代码片段,有啥解释吗? [复制]

以下代码片段 C++ 的说明

C++ 代码片段执行

此 Canon SDK C++ 代码片段的等效 C# 代码是啥?