文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何用c++表驱动替换if/else和switch/case语句

2024-04-02 19:55

关注

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++实现注意

代码:


// 3个文件,Client.cpp, TableDrave.h, TableDrive.cpp
 
// vvvvv Client.cpp begin
 
// ------------------------------------------------------------
// Name         :   Client.cpp
// Description  :   调用接口
// History      : 
// ------------------------------------------------------------
 
#include    "TableDrive.h"
 
// ------------------------------------------------------------
 
int main()
{
    TableDrive test;
    
    test.HandleKeyword(KEYWORD_A);
    test.HandleKeyword(KEYWORD_B);
    test.HandleKeyword(KEYWORD_C);
    test.HandleKeyword(KEYWORD_START);
    test.HandleKeyword(KEYWORD_D);
    
    return 0;
}
 
// ^^^^^ Client.cpp end
 
 
 
// vvvvv TableDrive.h begin
 
// ------------------------------------------------------------
// Name         :   TableDrive.h
// Description  :   表驱动头文件
// History      :   
// ------------------------------------------------------------
 
#ifndef     _TEST_DRIVE_H
#define     _TEST_DRIVE_H
 
 
#include    <map>
 
// ------------------------------------------------------------
 
// 测试用关键字
enum KEYWORD
{
    KEYWORD_START = -1,
    
    KEYWORD_A = 0,
    KEYWORD_B,
    KEYWORD_C,
    KEYWORD_D,  
    
    KEYWORD_END,
};
 
 
// ------------------------------------------------------------
 
// 可以使用 std:: 单个引用
using namespace std;
 
class TableDrive
{
public: 
 
    // ------------------------------------------------------------
    // Description : 
    //      根据关键字,执行处理函数
    // Parameters : 
    //      string keyword,关键字
    // Return Value : 
    //      bool,true,函数执行成功,false,找不到键字对应的函数,或函数执行失败
    // Errors : 
    //      无
    // ------------------------------------------------------------ 
    bool HandleKeyword(int keyword);
    
    // ------------------------------------------------------------
    // Description : 
    //      关联关键字到处理函数
    // Parameters : 
    //      无
    // Return Value : 
    //      bool,true,正常,false,异常
    // Errors : 
    //      无
    // ------------------------------------------------------------ 
    bool MapKeyToHandle();  
    
 
    TableDrive();
    
    ~TableDrive();
    
private:
    
    // vv 处理函数,true,执行成功,false,执行失败
    bool HandleKeyA();
    bool HandleKeyB();
    bool HandleKeyC();
    // ^^
    
private:
 
    // :TRICKY: 成员函数指针定义
    typedef bool (TableDrive:: *PHandle)(void);
    map<int, PHandle>   m_KeyToHandle;      // 关键字对应处理函数
};
 
#endif
 
// ^^^^^ TableDrive.h end
 
 
 
 
// vvvvv TableDrive.cpp begin
 
// ------------------------------------------------------------
// Name         :   TableDrive.cpp
// Description  :   表驱动实现文件
// History      : 
// ------------------------------------------------------------
 
#include    <stdio.h>
 
#include    "TableDrive.h"
 
// ------------------------------------------------------------
 
 
// 根据关键字,执行处理函数
bool TableDrive::HandleKeyword(int keyword)
{
    typedef map<int, PHandle>::const_iterator CI;
    CI iter = m_KeyToHandle.find(keyword);
 
    // 没有搜索到关键字
    if (m_KeyToHandle.end() == iter)
    {
        printf("\n  @@ search Keyword %d fail!\n", keyword);
        return false;
    }
 
    // :TRICKY: 注意成员函数指针的引用格式
    PHandle pFunction = iter->second;
    return (this->*pFunction)();
}
 
 
TableDrive::TableDrive()
{
    printf("\n  vv TableDrive::TableDrive()\n");
    MapKeyToHandle();
}
 
TableDrive::~TableDrive()
{
    printf("\n  ^^ TableDrive::~TableDrive()\n");
}
 
 
// ------------------------------------------------------------
 
// 关联关键字到处理函数
bool TableDrive::MapKeyToHandle()
{
    m_KeyToHandle[KEYWORD_A]    = &TableDrive::HandleKeyA;
    m_KeyToHandle[KEYWORD_B]    = &TableDrive::HandleKeyB;
    m_KeyToHandle[KEYWORD_C]    = &TableDrive::HandleKeyC;
        
    return true;
}
 
 
// 处理函数 A
bool TableDrive::HandleKeyA()
{
    printf("\n  ** A, HandleKeyA()\n\n");
    
    return true;
}
 
bool TableDrive::HandleKeyB()
{
    printf("\n  ** B, HandleKeyB()\n\n");
    
    return true;
}
 
bool TableDrive::HandleKeyC()
{
    printf("\n  ** C, HandleKeyC()\n\n");
    
    return true;
}
 
// ^^^^^ TableDrive.cpp end

关注点:

主要关注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.  鼠标操控。不同状态下移动鼠标,属于“状态判断、响应鼠标处理函数”流程。

 表驱动法

到此这篇关于使用c++表驱动法,替换复杂的if/else和switch/case语句的文章就介绍到这了,更多相关c++表驱动法内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯