首页 > C/C++语言 > C/C++基本语法 > 【C++提高】成员函数指针在开发中的实际应用
2006
01-18

【C++提高】成员函数指针在开发中的实际应用

【C++提高】成员函数指针在开发中的实际应用

作者:dozb

前几天我的《成员函数指针》一文,主要介绍了类成员函数指针的使用方法,大家看了后认为意义不大,那是因为你可能还没有真正在开发中遇到需要用成员函数指针的情况。这篇文章就作为《成员函数指针》一文补充,举例说明在什么情况下使用成员函数指针来简化开发。

设想我们要实现一个命令解释器类,就是这个类包括了若干个命令,通常我们的实现方法如下:

class CmdProcess
{
public:
     CmdProcess();
    int execCmd(char *cmd,int argc,char*argv[]);
    void getCmdHelp(char *cmd,char* cmdhelp);
private:
    int cmd_login(int argc,char*argv[]);
    int cmd_logout(int argc,char*argv[]);
    int cmd_putfile(int argc,char*argv[]);
    int cmd_getfile(int argc,char*argv[]);
    int cmd_listfile(int argc,char*argv[]);
    int cmd_delfile(int argc,char*argv[]);
};

//根据传入的命令名字和参数执行命令
int CmdProcess::execCmd(char *cmd,int argc,char*argv[])
{
    if(strcmp(cmd,”login”)==0)
     return   cmd_lo gin(argc,argv);
    else  if(strcmp(cmd,”logou t”)==0)
      return cmd_logout(argc,argv);
    else if(strcmp(cmd,”putfile”)==0)
      return cmd_putfile(argc,argv);
    else if(strcmp(cmd,”getfile”)==0)
     return  cmd_getfile( argc,argv);
    else if(strcmp(cmd,”listfile”)==0)
     return  cmd_listfile (argc,argv);
    else if(strcmp(cmd,”delfile”)==0)
     return  cmd_delfile( argc,argv);
     return -1;
}

//根据传入的命令名字获取命令的帮助信息
void CmdProcess::getCmdHelp(char *cmd,char* cmdhelp)
{
    if(strcmp(cmd,”login”)==0)
       …
    else  if(strcmp(cmd,”logou t”)==0)
       …
    else if(strcmp(cmd,”putfile”)==0)
       …
    else if(strcmp(cmd,”getfile”)==0)
       …
    else if(strcmp(cmd,”listfile”)==0)
       …
    else if(strcmp(cmd,”delfile”)==0)
       …
}

从上面可以看出,命令函数只是函数名不同,而参数和返回值相同,但是每次都要遍历所有的命令,烦不烦?更要命的是要是新增加一个命令,就需要修改所有的函数!假如你忘了修改一个地方,嘿嘿,后果是什么你也猜到了吧。

下面是用函数指针来实现相同的功能,可能看起来复杂一些,但要是遵循这个规则,使用起来还是比较简单的。

class CmdProcess
{
public:
     CmdProcess();
    int execCmd(char *cmd,int argc,char*argv[]);
    void getCmdHelp(char *cmd,char* cmdhelp);
private:
    typedef int (CmdProcess::* CMDFUN)(int argc,char*argv[]);//命令函数格式定义
    #define _CMDCOUNT 6
    struct _CMDINFO
    {
    char szCmdName[10];//命令名称
    char szCmdHelp[100];//命令帮助信息
    CMDFUN cmdFun;    //命令函数
    _CMDINFO(char* szCmdName,char* szCmdHelp,CMDFUN cmdFun)
    {
             strcpy(this->szCmdName,szCmdName);
        strcpy(this- >szCmdHelp,szCmdHelp);
        this->cmd Fun = cmdFun;
    };
    };
    _CMDINFO cmdInfoList[_CMDCOUNT];
    _CMDINFO * getCmdInfo(char *cmd);
private:
    int cmd_login(int argc,char*argv[]);
    int cmd_logout(int argc,char*argv[]);
    int cmd_putfile(int argc,char*argv[]);
    int cmd_getfile(int argc,char*argv[]);
    int cmd_listfile(int argc,char*argv[]);
    int cmd_delfile(int argc,char*argv[]);
};

//初始化成员函数指针的值
CmdProcess::CmdProcess()
{
    int i=0;
    cmdInfoList[i++] = _CMDINFO(“login”,”login ….”,cmd_login);
    cmdInfoList[i++] = _CMDINFO(“logout”,”logout ….”,cmd_logout);
    cmdInfoList[i++] = _CMDINFO(“putfile”,”putfile ….”,cmd_putfile);
    cmdInfoList[i++] = _CMDINFO(“getfile”,”getfile ….”,cmd_getfile);
    cmdInfoList[i++] = _CMDINFO(“listfile”,”listfile ….”,cmd_listfile);
    cmdInfoList[i++] = _CMDINFO(“delfile”,”delfile ….”,cmd_delfile);
}

//根据命令字找命令
_CMDINFO * CmdProcess::getCmdInfo(char *cmd)
{
   for(int i=0;i<_CMDCOUNT;i++)
   {
    if(strcmp(cmd,cmdInfoList.szCmdName)==0)
       return &cmdInfoList;
   }
   return NULL;
}

//根据传入的命令字和参数执行命令
int CmdProcess::execCmd(char *cmd,int argc,char*argv[])
{
   _CMDINFO * pCmdInfo = getCmdInfo(cmd);
   if(pCmdInfo)
      return (this->*(pCmdInfo->cmdFun))(argc,argv);//注意如何使用成员函数指针
   return -1;
}

//根据传入的命令字获取命令帮助信息
void CmdProcess::getCmdHelp(char *cmd,char* cmdhelp)
{
   _CMDINFO * pCmdInfo = getCmdInfo(cmd);
   if(pCmdInfo)
      strcpy(cmdhelp,pCmdInfo- >szCmdHelp);

}

这种方式,当新增命令时,需要修改命令个数,和把相应命令添加到cmdInfoList就可以了。


留下一个回复