如何用c++表驅(qū)動(dòng)替換if/else和switch/case語句
C++的表驅(qū)動(dòng)法
目的:使用表驅(qū)動(dòng)法,替換復(fù)雜的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代碼段,實(shí)際集成了3種類型邏輯:
1. 實(shí)現(xiàn)關(guān)鍵字的處理代碼;
2. 將關(guān)鍵字與處理代碼關(guān)聯(lián);
3. 以關(guān)鍵字選擇分支,執(zhí)行處理代碼;
我們將在一個(gè)switch代碼中維護(hù)3種變化。將1的處理代碼段,模塊化為函數(shù)后,變化點(diǎn)減少為2個(gè)。
在分支增加到幾十個(gè)時(shí),代碼維護(hù)性變得很差;而且switch對(duì)非整數(shù)類型無能為力。
二、表驅(qū)動(dòng)法
做法:
1. 將變化點(diǎn)2,做成一個(gè)[關(guān)鍵字:處理函數(shù)]映射結(jié)構(gòu)(推薦map容器),在獨(dú)立函數(shù)中賦值。
2. 將變化點(diǎn)3,做成一個(gè)查找關(guān)鍵字,執(zhí)行對(duì)應(yīng)函數(shù)的簡(jiǎn)單函數(shù)
好處:
1. 獨(dú)立出“選擇分支”變化點(diǎn),變?yōu)楣潭ǖ奶幚砹鞒獭?br />
2. 獨(dú)立出“關(guān)鍵字和處理函數(shù)的關(guān)聯(lián)”,易于維護(hù)。
限制條件:
1. 處理函數(shù)類型一樣(這在C++中不成問題);
2. 處理函數(shù)簡(jiǎn)單,但每個(gè)函數(shù)有差異(如果處理較為復(fù)雜,請(qǐng)使用創(chuàng)建型設(shè)計(jì)模式)
擴(kuò)展:
1. 對(duì)于處理函數(shù)由符合條件分支情況,變化點(diǎn)2使用list結(jié)構(gòu),按優(yōu)先級(jí)關(guān)聯(lián)處理函數(shù),使用 “職責(zé)鏈”形式的表驅(qū)動(dòng)法。
三、C++實(shí)現(xiàn)注意
代碼:
// 3個(gè)文件,Client.cpp, TableDrave.h, TableDrive.cpp
// vvvvv Client.cpp begin
// ------------------------------------------------------------
// Name : Client.cpp
// Description : 調(diào)用接口
// 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 : 表驅(qū)動(dòng)頭文件
// History :
// ------------------------------------------------------------
#ifndef _TEST_DRIVE_H
#define _TEST_DRIVE_H
#include <map>
// ------------------------------------------------------------
// 測(cè)試用關(guān)鍵字
enum KEYWORD
{
KEYWORD_START = -1,
KEYWORD_A = 0,
KEYWORD_B,
KEYWORD_C,
KEYWORD_D,
KEYWORD_END,
};
// ------------------------------------------------------------
// 可以使用 std:: 單個(gè)引用
using namespace std;
class TableDrive
{
public:
// ------------------------------------------------------------
// Description :
// 根據(jù)關(guān)鍵字,執(zhí)行處理函數(shù)
// Parameters :
// string keyword,關(guān)鍵字
// Return Value :
// bool,true,函數(shù)執(zhí)行成功,false,找不到鍵字對(duì)應(yīng)的函數(shù),或函數(shù)執(zhí)行失敗
// Errors :
// 無
// ------------------------------------------------------------
bool HandleKeyword(int keyword);
// ------------------------------------------------------------
// Description :
// 關(guān)聯(lián)關(guān)鍵字到處理函數(shù)
// Parameters :
// 無
// Return Value :
// bool,true,正常,false,異常
// Errors :
// 無
// ------------------------------------------------------------
bool MapKeyToHandle();
TableDrive();
~TableDrive();
private:
// vv 處理函數(shù),true,執(zhí)行成功,false,執(zhí)行失敗
bool HandleKeyA();
bool HandleKeyB();
bool HandleKeyC();
// ^^
private:
// :TRICKY: 成員函數(shù)指針定義
typedef bool (TableDrive:: *PHandle)(void);
map<int, PHandle> m_KeyToHandle; // 關(guān)鍵字對(duì)應(yīng)處理函數(shù)
};
#endif
// ^^^^^ TableDrive.h end
// vvvvv TableDrive.cpp begin
// ------------------------------------------------------------
// Name : TableDrive.cpp
// Description : 表驅(qū)動(dòng)實(shí)現(xiàn)文件
// History :
// ------------------------------------------------------------
#include <stdio.h>
#include "TableDrive.h"
// ------------------------------------------------------------
// 根據(jù)關(guān)鍵字,執(zhí)行處理函數(shù)
bool TableDrive::HandleKeyword(int keyword)
{
typedef map<int, PHandle>::const_iterator CI;
CI iter = m_KeyToHandle.find(keyword);
// 沒有搜索到關(guān)鍵字
if (m_KeyToHandle.end() == iter)
{
printf("\n @@ search Keyword %d fail!\n", keyword);
return false;
}
// :TRICKY: 注意成員函數(shù)指針的引用格式
PHandle pFunction = iter->second;
return (this->*pFunction)();
}
TableDrive::TableDrive()
{
printf("\n vv TableDrive::TableDrive()\n");
MapKeyToHandle();
}
TableDrive::~TableDrive()
{
printf("\n ^^ TableDrive::~TableDrive()\n");
}
// ------------------------------------------------------------
// 關(guān)聯(lián)關(guān)鍵字到處理函數(shù)
bool TableDrive::MapKeyToHandle()
{
m_KeyToHandle[KEYWORD_A] = &TableDrive::HandleKeyA;
m_KeyToHandle[KEYWORD_B] = &TableDrive::HandleKeyB;
m_KeyToHandle[KEYWORD_C] = &TableDrive::HandleKeyC;
return true;
}
// 處理函數(shù) 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
關(guān)注點(diǎn):
主要關(guān)注3個(gè)點(diǎn),維護(hù)第2、3點(diǎn)
1. HandleKeyword(),根據(jù)關(guān)鍵字,執(zhí)行處理函數(shù)。固定后基本不改變;
2. MapKeyToHandle(),關(guān)聯(lián)關(guān)鍵字到處理函數(shù);
3. Handle(),各個(gè)處理函數(shù)
成員函數(shù)指針使用注意
1. 聲明格式,與C相比,函數(shù)指針前要包含類域;
typedef bool (TableDrive:: *PHandle)();
2. 聲明位置,包含在類中,否則不能識(shí)別類域標(biāo)志;
3. 賦值語法格式,與C相比,函數(shù)指針前要包含類域;
PHandle pFunction = &TableDrive::HandleKeyA;
4. 調(diào)用語法格式,與C相比,需要加上this,并以強(qiáng)制解引用方式調(diào)用;
(this->*pFunction)();
四、實(shí)用案例
1. 菜單調(diào)節(jié)。一個(gè)模塊,有幾十個(gè)菜單參數(shù)可以調(diào)節(jié),每個(gè)菜單調(diào)節(jié)的步進(jìn)、范圍不同,但都是“觸發(fā)消息、調(diào)節(jié)數(shù)值”流程。
2. 按鍵響應(yīng)。多個(gè)按鍵,屬于“按鍵,執(zhí)行對(duì)應(yīng)處理函數(shù)”流程。
3. 鼠標(biāo)操控。不同狀態(tài)下移動(dòng)鼠標(biāo),屬于“狀態(tài)判斷、響應(yīng)鼠標(biāo)處理函數(shù)”流程。
表驅(qū)動(dòng)法

到此這篇關(guān)于使用c++表驅(qū)動(dòng)法,替換復(fù)雜的if/else和switch/case語句的文章就介紹到這了,更多相關(guān)c++表驅(qū)動(dòng)法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言數(shù)據(jù)結(jié)構(gòu)之雙向循環(huán)鏈表的實(shí)例
這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)之雙向循環(huán)鏈表的實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-06-06
C語言中求字符串長(zhǎng)度的函數(shù)的幾種實(shí)現(xiàn)方法
這篇文章主要介紹了C語言中求字符串長(zhǎng)度的函數(shù)的幾種實(shí)現(xiàn)方法,需要的朋友可以參考下2018-08-08
c語言中十進(jìn)制轉(zhuǎn)二進(jìn)制顯示小工具的實(shí)現(xiàn)代碼
本篇文章是對(duì)c語言中十進(jìn)制轉(zhuǎn)二進(jìn)制顯示小工具的實(shí)現(xiàn)代碼進(jìn)行了詳細(xì)的分析的介紹,需要的朋友參考下2013-05-05
C++11中列表初始化機(jī)制的概念與實(shí)例詳解
在我們實(shí)際編程中,我們經(jīng)常會(huì)碰到變量初始化的問題,對(duì)于不同的變量初始化的手段多種多樣,下面這篇文章主要給大家介紹了關(guān)于C++11中列表初始化機(jī)制的相關(guān)資料,需要的朋友可以參考下2021-11-11
使用C語言求二叉樹結(jié)點(diǎn)的最低公共祖先的方法
這篇文章主要介紹了使用C語言求二叉樹結(jié)點(diǎn)的最低公共祖先的方法,文中還給出了ACM的練習(xí)題目,需要的朋友可以參考下2015-08-08

