2017-06-02 3 views
-1

J'ai un code simple de style C qui implémente un interpréteur de commandes simples comme suit:Comment rendre un tableau de pointeurs de fonction privé en C++?

typedef struct { 
    char *name; 
    int (*func)(char* args); 
} sCOMMAND; 

int func_reset(char* args); 
int func_acc(char* args); 
int func_dec(char* args); 

const sCOMMAND CmdTbl[] = { 
    { "RST", func_reset }, 
    { "ACC", func_acc }, 
    { "DEC", func_dec } 
}; 

void ProcessCommand (char *cCmd) 
{ 
    int ndx = NUM_CMDS; 

    // shortest cmd is 3 chars 
    if (strlen(cCmd) >= MIN_CMD_LEN) 
    { 
     ///////////////////////////////////////////////////// 
     // Chop the command line into substrings with ptr to 
     // each one where *parm[0] points to the command. 
     char *parms[MAX_PARMS]; 
     ParseCommand(cCmd, parms); 

     ///////////////////////////////////////////////////// 
     // Scan the command table looking for a match 
     for (int ndx = 0; ndx < NUM_CMDS; ndx++) 
     { 
      if (stricmp (CmdTbl[ndx].name, &parms[0]) == 0) 
      { 
       // command found, run its function 
       CmdTbl[ndx].func(parms); 
      } 
     } 
    } 

    // no valid command was found 
    if (ndx == NUM_CMDS) 
     Serial.println("UNKNOWN COMMAND"); 

    Serial.println("RDY> "); 
} 

Cela fonctionne, mais ce que je voudrais faire est encapsulent l'interpréteur de commandes dans une classe C++. Mais je n'ai pas réussi à obtenir la table sCOMMAND avec les méthodes de classe. Ma récente tentative:

// dans le fichier CmdHandler.h

class CmdHandler; 

typedef struct { 
    char *name; 
    int (CmdHandler::*func)(char* args); 
} sCOMMAND; 


class CmdHandler 
{ 
    public: 
     CmdHandler(int buf_size); 
     ~CmdHandler(void) { if (m_Buf) delete [] m_Buf; }; 
     void ProcessCommand (char *cCmd); 

    private: 
     char  *m_Buf; 
     int   m_BufSize; 
     char  *parms[MAX_PARMS]; 
     void ParseCommand(char *cCmd, char* (&parms)[MAX_PARMS]); 

     int func_1(char* args); 
     int func_2(char* args); 
     int func_3(char* args); 

     sCOMMAND CmdTbl[3]; 
}; 

// dans le fichier CmdHandler.cpp

#include "CmdHandler.h" 


CmdHandler::CmdHandler(int buf_size) 
    : CmdTbl{ {"RST", func_1}, 
       {"ACC", func_2}, 
       {"DEC", func_3} } 
{ 
    m_BufSize = buf_size; 

    m_Buf = new char[m_BufSize]; 
} 

void CmdHandler::ProcessCommand (char *cCmd) 
{ 

} 

ARM compilateur GCC RPC, ce qui donne une erreur "cannot convert 'CmdHandler::func_1' from type 'int (CmdHandler::)(char*)' to type 'int (CmdHandler::*)(char*)'".

Si je sors la référence du pointeur de la structure comme:

typedef struct { 
    char *name; 
    int (CmdHandler::func)(char* args); 
} sCOMMAND; 

Je reçois

"CmdHandler.h: invalid use of incomplete type 'class CmdHandler' 
     int (CmdHandler::func)(char* args);". 

Quelqu'un peut-il me dire comment résoudre ce ou de suggérer une meilleure façon?

+0

Faites ces fonctions 'static'. –

Répondre

0

À la différence des fonctions non membres, les fonctions membres ne sont pas affectées aux pointeurs de fonction. Par conséquent, vous devez utiliser:

CmdHandler::CmdHandler(int buf_size) 
    : cmd_tbl{ {"RST", &CmdHandler::func_1}, 
       {"ACC", &CmdHandler::func_2}, 
       {"DEC", &CmdHandler::func_3} } 
{ 
    m_BufSize = buf_size; 

    m_Buf = new char[m_BufSize]; 
} 
+0

Cela a été compilé, mais donne désormais une erreur de lien (pour chaque méthode): "référence non définie à' CmdHandler :: func_1 (char *) '". Ceci a été marqué comme un doublon; laissez-moi regarder l'original ... – RayZ

+1

@RayZ, je suggère de créer un [mcve] qui produit l'erreur de l'éditeur de liens et de demander cela dans un post SO séparé. –

+0

@RayZ Avez-vous implémenté ces fonctions (puisque vous ne l'avez pas fait dans l'exemple de code fourni)? – drescherjm