• C++ 再谈谈注册(本质是建立映射)与回调


      在之前的博文中, 我们探讨过映射的重要作用, 请直接看:http://blog.csdn.net/stpeace/article/details/39452203, 在那篇文章中, 我们是用STL中的map来做的, map建立的是key-value映射, 在本文中, 我们自己来建立映射, 并讨论一个更为复杂的程序, 顺便再次复习一下注册与回调。

    注册与回调? 有那么复杂么?没有必要过多地扯了, 直接上代码:

      1 #include <iostream>
      2 #include <vector>
      3 using namespace std;
      4  
      5 // 前向声明
      6 class BasicMod;
      7  
      8  
      9 //类函数指针类型
     10 typedef void (BasicMod:: *PFun)(const char* pParaName); 
     11  
     12  
     13 // 映射结点
     14 typedef struct
     15 {
     16     BasicMod *pMod;
     17     char szParaName[1024];
     18     PFun operTypeOne;
     19     PFun operTypeTwo;
     20     PFun operTypeThree;
     21 }MyMap;
     22  
     23  
     24 // 用全局的g_pv保存结点指针
     25 vector<MyMap *> g_pv;
     26  
     27  
     28 // 执行类, 提供注册, 查找接口, 并执行回调操作
     29 class Do
     30 {
     31 public:
     32     // 单例
     33     static Do *getInstance()
     34     {
     35         static Do *p = NULL;
     36         if(NULL == p)
     37         {
     38             p = new Do;
     39         }
     40  
     41         return p;
     42     }
     43  
     44     // 注册接口
     45     void regNode(BasicMod *pb, MyMap *pmap, int i)
     46     {
     47         MyMap *p = new MyMap;
     48         p->pMod = pb;
     49         memset(p->szParaName, 0, sizeof(p->szParaName));
     50         strncpy(p->szParaName, (pmap + i)->szParaName, sizeof(p->szParaName) - 1);
     51         p->operTypeOne = (pmap + i)->operTypeOne;
     52         p->operTypeTwo = (pmap + i)->operTypeTwo;
     53         p->operTypeThree = (pmap + i)->operTypeThree;
     54  
     55         g_pv.push_back(p);
     56     }
     57  
     58     // 查找接口
     59     MyMap *findNode(const char *pParaName)
     60     {
     61         int n = g_pv.size();
     62         int i = 0;
     63         for(i = 0; i < n; i++)
     64         {
     65             if(0 == strcmp(g_pv[i]->szParaName, pParaName))
     66             {
     67                 return g_pv[i];
     68             }
     69         }
     70  
     71         return NULL;
     72     }
     73  
     74     // 执行回调操作
     75     void exect(const char *pParaName)
     76     {
     77         MyMap *p = findNode(pParaName);
     78         if(NULL != p && NULL != p->pMod)
     79         {
     80             ((p->pMod)->*(p->operTypeOne))(pParaName);
     81             ((p->pMod)->*(p->operTypeTwo))(pParaName);
     82             ((p->pMod)->*(p->operTypeThree))(pParaName);
     83         }
     84     }
     85 };
     86  
     87  
     88 // 基类
     89 class BasicMod
     90 {
     91 public:
     92     void reg(BasicMod *pm, MyMap *p, int i)
     93     {
     94         Do::getInstance()->regNode(pm, p, i);    
     95     }
     96 };
     97  
     98  
     99 // 格式化
    100 #define TOGETHER(mod, name, f1, f2, f3) {NULL, name, (PFun)(&mod::f1), (PFun)(&mod::f2), (PFun)(&mod::f3)}
    101  
    102  
    103 // 模块1
    104 class Mod1 : public BasicMod
    105 {
    106 public:
    107     static Mod1* getInstance()
    108     {
    109         static Mod1* p = NULL;
    110         if(NULL == p)
    111         {
    112             p = new Mod1;
    113         }
    114  
    115         return p;
    116     }
    117  
    118     // 模块1的初始化
    119     void init()
    120     {
    121         MyMap mapArr[] = 
    122         {
    123             TOGETHER(Mod1, "cpu", fun1Cpu, fun2Cpu, fun3Cpu),
    124         };
    125  
    126         int n = sizeof(mapArr) / sizeof(mapArr[0]);
    127         int i = 0;
    128         for(i = 0; i < n; i++)
    129         {
    130             // 注册
    131             reg(getInstance(), mapArr, i);
    132         }
    133     }
    134  
    135     // 提供回调接口
    136     void fun1Cpu(const char *pParaName)
    137     {
    138         cout << "mod1, pParaName is " << pParaName << endl;
    139     }
    140  
    141     // 提供回调接口
    142     void fun2Cpu(const char *pParaName)
    143     {
    144         cout << "mod1, pParaName is " << pParaName << endl;
    145     }
    146  
    147     // 提供回调接口
    148     void fun3Cpu(const char *pParaName)
    149     {
    150         cout << "mod1, pParaName is " << pParaName << endl;
    151     }
    152 };
    153  
    154  
    155 class Mod2 : public BasicMod
    156 {
    157 public:
    158     static Mod2* getInstance()
    159     {
    160         static Mod2* p = NULL;
    161         if(NULL == p)
    162         {
    163             p = new Mod2;
    164         }
    165  
    166         return p;
    167     }
    168  
    169     void init()
    170     {
    171         MyMap mapArr[] = 
    172         {
    173             TOGETHER(Mod2, "flash", fun1Flash, fun2Flash, fun3Flash),
    174         };
    175  
    176         int n = sizeof(mapArr) / sizeof(mapArr[0]);
    177         int i = 0;
    178         for(i = 0; i < n; i++)
    179         {
    180             reg(getInstance(), mapArr, i);
    181         }
    182     }
    183  
    184     void fun1Flash(const char *pParaName)
    185     {
    186         cout << "mod2, pParaName is " << pParaName << endl;
    187     }
    188  
    189     void fun2Flash(const char *pParaName)
    190     {
    191         cout << "mod2, pParaName is " << pParaName << endl;
    192     }
    193  
    194     void fun3Flash(const char *pParaName)
    195     {
    196         cout << "mod2, pParaName is " << pParaName << endl;
    197     }
    198 };
    199  
    200  
    201 int main()
    202 {
    203     // 模块初始化
    204     Mod1::getInstance()->init();
    205     Mod2::getInstance()->init();
    206  
    207     // 执行操作
    208     Do::getInstance()->exect("cpu");
    209     Do::getInstance()->exect("flash");
    210     Do::getInstance()->exect("mem");
    211  
    212     return 0;
    213 }

    程序的结果为:

     

    mod1, pParaName is cpu
    mod1, pParaName is cpu
    mod1, pParaName is cpu
    mod2, pParaName is flash
    mod2, pParaName is flash
    mod2, pParaName is flash

    我们也可以对上述程序作一下等价变换, 得到:

      1 #include <iostream>
      2 #include <vector>
      3 using namespace std;
      4  
      5 // 前向声明
      6 class BasicMod;
      7  
      8  
      9 //类函数指针类型
     10 typedef void (BasicMod:: *PFun)(const char* pParaName); 
     11  
     12  
     13 // 映射结点
     14 typedef struct
     15 {
     16     BasicMod *pMod;
     17     char szParaName[1024];
     18     PFun operTypeOne;
     19     PFun operTypeTwo;
     20     PFun operTypeThree;
     21 }MyMap;
     22  
     23  
     24 // 用全局的g_pv保存结点指针
     25 vector<MyMap *> g_pv;
     26  
     27  
     28 // 执行类, 提供注册, 查找接口, 并执行回调操作
     29 class Do
     30 {
     31 public:
     32     // 单例
     33     static Do *getInstance()
     34     {
     35         static Do *p = NULL;
     36         if(NULL == p)
     37         {
     38             p = new Do;
     39         }
     40  
     41         return p;
     42     }
     43  
     44     // 注册接口
     45     void regNode(BasicMod *pm, const char *pParaName, PFun one, PFun two, PFun three)
     46     {
     47         MyMap *p = new MyMap;
     48         p->pMod = pm;
     49         memset(p->szParaName, 0, sizeof(p->szParaName));
     50         strncpy(p->szParaName, pParaName, sizeof(p->szParaName) - 1);
     51         p->operTypeOne = one;
     52         p->operTypeTwo = two;
     53         p->operTypeThree = three;
     54  
     55         g_pv.push_back(p);
     56     }
     57  
     58     // 查找接口
     59     MyMap *findNode(const char *pParaName)
     60     {
     61         int n = g_pv.size();
     62         int i = 0;
     63         for(i = 0; i < n; i++)
     64         {
     65             if(0 == strcmp(g_pv[i]->szParaName, pParaName))
     66             {
     67                 return g_pv[i];
     68             }
     69         }
     70  
     71         return NULL;
     72     }
     73  
     74     // 执行回调操作
     75     void exect(const char *pParaName)
     76     {
     77         MyMap *p = findNode(pParaName);
     78         if(NULL != p && NULL != p->pMod)
     79         {
     80             ((p->pMod)->*(p->operTypeOne))(pParaName);
     81             ((p->pMod)->*(p->operTypeTwo))(pParaName);
     82             ((p->pMod)->*(p->operTypeThree))(pParaName);
     83         }
     84     }
     85 };
     86  
     87  
     88 // 基类
     89 class BasicMod
     90 {
     91 public:
     92     void reg(const char *pParaName, PFun one, PFun two, PFun three)
     93     {
     94         Do::getInstance()->regNode(this, pParaName, one, two, three);    
     95     }
     96 };
     97  
     98  
     99 // 格式化
    100 #define TOGETHER(mod, name, f1, f2, f3) {NULL, name, (PFun)(&mod::f1), (PFun)(&mod::f2), (PFun)(&mod::f3)}
    101  
    102  
    103 // 模块1
    104 class Mod1 : public BasicMod
    105 {
    106 public:
    107     static Mod1* getInstance()
    108     {
    109         static Mod1* p = NULL;
    110         if(NULL == p)
    111         {
    112             p = new Mod1;
    113         }
    114  
    115         return p;
    116     }
    117  
    118     // 模块1的初始化
    119     void init()
    120     {
    121         MyMap mapArr[] = 
    122         {
    123             TOGETHER(Mod1, "cpu", fun1Cpu, fun2Cpu, fun3Cpu),
    124         };
    125  
    126         int n = sizeof(mapArr) / sizeof(mapArr[0]);
    127         int i = 0;
    128         for(i = 0; i < n; i++)
    129         {
    130             // 注册
    131             reg(mapArr[i].szParaName, mapArr[i].operTypeOne, mapArr[i].operTypeTwo, mapArr[i].operTypeThree);
    132         }
    133     }
    134  
    135     // 提供回调接口
    136     void fun1Cpu(const char *pParaName)
    137     {
    138         cout << "mod1, pParaName is " << pParaName << endl;
    139     }
    140  
    141     // 提供回调接口
    142     void fun2Cpu(const char *pParaName)
    143     {
    144         cout << "mod1, pParaName is " << pParaName << endl;
    145     }
    146  
    147     // 提供回调接口
    148     void fun3Cpu(const char *pParaName)
    149     {
    150         cout << "mod1, pParaName is " << pParaName << endl;
    151     }
    152 };
    153  
    154  
    155 class Mod2 : public BasicMod
    156 {
    157 public:
    158     static Mod2* getInstance()
    159     {
    160         static Mod2* p = NULL;
    161         if(NULL == p)
    162         {
    163             p = new Mod2;
    164         }
    165  
    166         return p;
    167     }
    168  
    169     void init()
    170     {
    171         MyMap mapArr[] = 
    172         {
    173             TOGETHER(Mod2, "flash", fun1Flash, fun2Flash, fun3Flash),
    174         };
    175  
    176         int n = sizeof(mapArr) / sizeof(mapArr[0]);
    177         int i = 0;
    178         for(i = 0; i < n; i++)
    179         {
    180             reg(mapArr[i].szParaName, mapArr[i].operTypeOne, mapArr[i].operTypeTwo, mapArr[i].operTypeThree);
    181         }
    182     }
    183  
    184     void fun1Flash(const char *pParaName)
    185     {
    186         cout << "mod2, pParaName is " << pParaName << endl;
    187     }
    188  
    189     void fun2Flash(const char *pParaName)
    190     {
    191         cout << "mod2, pParaName is " << pParaName << endl;
    192     }
    193  
    194     void fun3Flash(const char *pParaName)
    195     {
    196         cout << "mod2, pParaName is " << pParaName << endl;
    197     }
    198 };
    199  
    200  
    201 int main()
    202 {
    203     // 模块初始化
    204     Mod1::getInstance()->init();
    205     Mod2::getInstance()->init();
    206  
    207     // 执行操作
    208     Do::getInstance()->exect("cpu");
    209     Do::getInstance()->exect("flash");
    210     Do::getInstance()->exect("mem");
    211  
    212     return 0;
    213 }

    我们看到, 上述程序建立了一个name对于{f1, f2, f3}的映射, 适用范围更广。

    而且, 以后如果再加字段, 程序猿只需要注意三处即可: 1. 增加initialize函数中数组中的项(增加映射);2. 在类中实现回调接口(增加回调接口); 3.在main中启动调用(启动执行)。

    当然啦, 如果要增加模块3, 那也是很easy的。

     

    反思一下:我突然发现, 我把上面的程序写复杂了, 其实, 也可以用STL map建立name到f1, f2, f3的映射, 此时, 要把{f1, f2, f3}看成一个整体, 上述程序用STL map进行改造后, 会更好, 有兴趣的朋友可以试试。 我相信: 一次刻骨铭心的体验胜过千百次说教。

  • 相关阅读:
    php提示undefined index的几种解决方法
    划分树(poj2104)
    ACM-ICPC 2018 南京赛区网络预赛B
    AC Challenge(状压dp)
    UVALive5966(bfs)
    UVALive
    STL next_permutation 算法原理和实现
    凸包算法
    poj1873(枚举+凸包)
    CodeForces
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/16566461.html
Copyright © 2020-2023  润新知