首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

C++ 函數映射表完整實作:Map 與 Array 兩種策略效能比較

     編輯:更多程式設計知識

前言

面對大量 if-else 或 switch-case 分支,程式碼會變得臃腫難維護。C++ 提供函數指標與成員函數指標機制,配合 std::map 或陣列建立「鍵值→函數」映射,實現 O(log N) 或 O(1) 分派。本文完整示範兩種策略並比較優劣。

核心型別定義

enum type_func {
  type_begin = -1,
  type_eat, type_sleep, type_walk, type_run,
  type_smile, type_cry, type_jump,
  type_max_size
};

class CAnimal {
public:
  typedef int (CAnimal::*ptr_func)(bool);  // 成員函數指標型別

protected:
  static std::map s_map;   // Map 策略
  static ptr_func s_array[type_max_size];       // Array 策略

public:
  CAnimal() {
    memset(s_array, 0, sizeof(s_array));
    Init();
  }
  // ... 七個行為函數:eat, sleep, walk, run, smile, cry, jump
  // 皆回傳 int,參數 bool,預設 true
};

初始化映射表

void CAnimal::Init() {
  // Map 映射
  s_map[type_eat]   = &CAnimal::eat;
  s_map[type_sleep] = &CAnimal::sleep;
  s_map[type_walk]  = &CAnimal::walk;
  s_map[type_run]   = &CAnimal::run;
  s_map[type_smile] = &CAnimal::smile;
  s_map[type_cry]   = &CAnimal::cry;
  s_map[type_jump]  = &CAnimal::jump;

  // Array 映射(索引對應 enum 值)
  s_array[type_eat]   = &CAnimal::eat;
  s_array[type_sleep] = &CAnimal::sleep;
  s_array[type_walk]  = &CAnimal::walk;
  s_array[type_run]   = &CAnimal::run;
  s_array[type_smile] = &CAnimal::smile;
  s_array[type_cry]   = &CAnimal::cry;
  s_array[type_jump]  = &CAnimal::jump;
}

// 靜態成員定義(放在類別外)
std::map CAnimal::s_map;
CAnimal::ptr_func CAnimal::s_array[type_max_size];

三種分派方式比較

1. 傳統 switch-case

void Process(type_func type) {
  switch (type) {
    case type_eat:   eat();   break;
    case type_sleep: sleep(); break;
    // ...
  }
}

優點:直觀;缺點:分支多時臃腫、擴充需修改核心邏輯、O(N) 線性比對。

2. Map 映射分派

void ProcessByUseMap(int key, bool val) {
  auto it = s_map.find(static_cast(key));
  if (it != s_map.end()) {
    ptr_func pFun = it->second;
    if (pFun) (this->*pFun)(val);
  }
}

優點:動態擴充、鍵值不需連續、O(log N) 查找;缺點:記憶體開銷大(紅黑樹節點)、需包含 <map>。

3. Array 映射分派

void ProcessByUseArray(int key, bool val) {
  if (type_begin < key && key < type_max_size) {
    ptr_func pFun = s_array[key];
    if (pFun) (this->*pFun)(val);
  }
}

優點:O(1) 直接索引、記憶體緊湊、無動態分配;缺點:enum 值必須連續、擴充需調整陣列大小與 enum 定義。

運算子多載語法糖

// Map 版 operator[]
int operator[](int key) {
  auto it = s_map.find(static_cast(key));
  if (it != s_map.end()) {
    ptr_func pFun = it->second;
    if (pFun) return (this->*pFun)(false);
  }
  return NULL;
}

// Array 版 operator()
int operator()(int key, bool val) {
  if (type_begin < key && key < type_max_size) {
    ptr_func pFun = s_array[key];
    if (pFun) return (this->*pFun)(val);
  }
  return NULL;
}

使用方式:

CAnimal dog;
dog[type_eat];           // Map 版,預設 false
dog(type_run, true);     // Array 版,傳 true

非成員函數映射(全域函數)

void func_eat(int = 0) {}
void func_run(int = 0) {}
// ...

typedef void (*ptrFun)(int);
std::map g_map;
ptrFun g_array[type_max_size];

// 初始化
g_map[type_eat] = func_eat;
g_array[type_eat] = func_eat;

// 使用
g_map[type_eat](1);
g_array[type_run](2);

效能與選型建議

指標MapArraySwitch
查找複雜度O(log N)O(1)O(N)
記憶體開銷高(樹節點)低(連續陣列)極低
鍵值連續性不需連續必須連續不需連續
動態擴充容易麻煩(需改 enum/陣列)麻煩
適用場景插件系統、動態註冊、稀疏鍵值高頻熱路徑、固定協定、效能關鍵分支少、邏輯簡單

進階:抽象基類策略(策略模式)

本文著重 Map/Array 兩種指標映射。若需更強的型別安全與擴充性,可定義抽象介面 IAction,每個行為實作一個類別,配合 Factory 模式管理。此為策略模式,屬於物件導向層面的解法,不在本文範圍內。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved