想想我們在遇到多語句分支時是不是首先想到的是 switc case 和 if else if ...
這2種方式在編碼方面確實簡單少,但是當分支達到一定數量後,特別是分支內部有嵌套大段代碼或者再嵌套分支,
代碼會顯得異常臃腫,十分難以維護,對於if else if 語句過多的分支帶來過多的判定句,勢必會影響效率。
3種替代方法簡述:
1.使用map,需要構建樹和節點,比數組的方式消耗更多的記憶體,查詢時間複雜度為Log(N),但擴充起來方便。
2.使用數組,查詢直接索引定位, 一般來講我們是連續的初始化數組,也就意味索引(type_func)到函數的映射要連續,
所以使用數組索引在擴充上來講:例如增刪元素是稍微麻煩點的。
3. 使用C++的特性---抽象繼承來實現,本文只講前2種的使用,這種方式以後再補充。
我比較喜歡用代碼結合實際來講解,下面我將以一段案例代碼來講解如何使用這幾種映射:
// 動物會一些動作enumtype_func{type_begin = -1,type_eat,type_sleep,type_walk,type_run,type_smile,type_cry,type_jump,type_max_size,};classCAnimal{public:typedefint(CAnimal::*ptr_func)(bool);protected:static map<type_func,ptr_func>s_map;static ptr_funcs_array[type_max_size];public:CAnimal(){memset(s_array,0,sizeof(s_array));Init();}// 需要映射函數的傳回值 和 參數必須 統一inteat(bool= true){return printf("eatn"),1;}intsleep(bool= true){return printf("sleepn"),1;}intwalk(bool= true){return printf("walkn"),1;}intrun(bool= true){return printf("runn"),1;}intsmile(bool= true){return printf("smilen"),1;}intcry(bool= true){return printf("cryn"),1;}intjump(bool= true){return printf("jumpn"),1;}// 初始化voidInit(){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;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;}// 一般做法是switc case 或者 if else... // 其實這裡看起來還不算糟糕,一方面這裡我把每個模組內容都封裝到相應函數了// 分支內部才會看起來相對簡潔,實際編碼中可能就不是你現在所看到的方式。voidProcess (type_func type){switch (type){case type_eat:eat();break;case type_sleep:sleep();break;case type_walk:walk();break;case type_run:run();break;case type_smile:smile();break;case type_cry:cry();break;case type_jump:jump();break;}}// 很熟悉的感覺吧! voidProcess2(type_func type){if (type_eat == type){eat();}else if (type_sleep == type){sleep();}else if (type_walk == type){walk();}else if (type_run == type){run();}else if (type_smile == type){smile();}else if (type_cry == type){cry();}else if (type_jump == type){jump();}}// 使用map 映射void ProcessByUseMap(int key, bool val){map<type_func,ptr_func>::iterator it = s_map.find((type_func)key);if (it != s_map.end()){ptr_func pFun = it->second;if (pFun)(this->*pFun)(val);}}// 使用數組 映射void ProcessByUseArray(int key, bool val){// 數組if (type_begin < key && type_max_size > key){ptr_func pFun = s_array[key];if (pFun)(this->*pFun)(val);}}// 使用map 映射intoperator[](int key){map<type_func,ptr_func>::iterator it = s_map.find((type_func)key);if (it != s_map.end()){ptr_func pFun = it->second;if (pFun)return (this->*pFun)(false);}return NULL;}// 使用數組 映射int operator()(int key,bool val){if (type_begin < key && type_max_size > key){ptr_func pFun = s_array[key];if (pFun)return (this->*pFun)(val);}return NULL;}};map<type_func, CAnimal::ptr_func>CAnimal::s_map;CAnimal::ptr_funcCAnimal::s_array[type_max_size];//////////////////////////////////////////////////////////////////////////// 非成員函數voidfunc_eat(int = 0){}voidfunc_run(int = 0){}voidfunc_walk(int =0){}voidfunc_cry(int = 0){}typedef void(*ptrFun)(int);map<type_func,ptrFun>g_map;ptrFung_array[type_max_size];int _tmain(int argc, _TCHAR* argv[]){//////////////////////////////////////////////////////////////////////////// 為了便於說明,下面代碼不做安全檢查// 非成員函數映射2種用法// initg_map[type_eat] = func_eat;g_map[type_run] = func_run;g_map[type_walk] = func_walk;g_map[type_cry] = func_cry;g_array[type_eat] = func_eat;g_array[type_run] = func_run;g_array[type_walk] = func_walk;g_array[type_cry] = func_cry;// usingg_map[type_eat](1);g_map[type_run](2);g_map[type_walk](3);g_map[type_cry](4);g_array[type_eat](1);g_array[type_run](2);g_array[type_walk](3);g_array[type_cry](4);//////////////////////////////////////////////////////////////////////////// 成員函數映射使用CAnimal Dog;Dog.Process(type_eat);Dog.ProcessByUseMap(type_run,true);Dog.ProcessByUseArray(type_cry,false);Dog[type_walk];Dog(type_sleep,true);Dog(type_run,false);return 1;}