2014-10-10 2 views
0

Я хочу сделать что-то вроде этого:C++ указатель на метод класса

struct CLI_Command{ 
    CLI_Command(char* s, void (*h)(void)){ 
     command_string = s; 
     handler = h; 
    } 

    char* command_string; 
    void (*handler)(void); 
}; 

class CLI { 
    public: 
     CLI(); 

    private: 
     CLI_Command cli_table[NO_CLI_COMMANDS] = { 
       CLI_Command("Command1", handler1), 
       CLI_Command("Command2", handler2) 
     }; 

     void handler1(){}; 
     void handler2(){}; 
}; 

Я знаю, что мне нужно что-то похожее на CLI :: * обработчик, но я не могу получить правильный синтаксис. Я постоянно работает в ошибки, как это:

"error: no matching function for call to 'CLI_Command::CLI_Command(const char [4], <unresolved overloaded function type>)" 
+0

Проблема заключается в том, что вы пытаетесь взять адрес нестатической функции члена, который неразрешенный. Я недавно ответил на этот вопрос (http://stackoverflow.com/a/25953204/1392132). Может быть, это поможет вам. Обратите внимание, что современный C++ предоставляет мощные инструменты для записи вашей программы намного чище и безопаснее. – 5gon12eder

+1

@ 5gon12eder: Совершенно законно принимать адрес нестатической функции-члена, но результатом является указатель-на-член, а не указатель на функцию. –

+0

@ 5gon12eder ОК, можете ли вы подробно остановиться на этих инструментах? Или указать мне в каком-то направлении? :). Я делаю интерфейс командной строки через UART на встроенном устройстве. – Jolle

ответ

3

Это иллюстрирует правильный синтаксис:

class CLI; 

struct CLI_Command 
{ 
    CLI_Command(char* s, void (CLI::*h)(void)) 
    { 
     command_string = s; 
     handler = h; 
    } 

    char* command_string; 
    void (CLI::*handler)(void); 

    void raise(CLI* the_cli) { return (the_cli->*handler)(); } 
}; 

class CLI 
{ 
    public: 
     CLI(); 

    private: 
     static CLI_Command cli_table[NO_CLI_COMMANDS]; 

     void handler1(){}; 
     void handler2(){}; 
}; 

CLI::CLI_Command cli_table[NO_CLI_COMMANDS] = { 
    { "Command1", &CLI::handler1 }, 
    { "Command2", &CLI::handler2 } 
}; 

Имена функций-членов не разлагаются на указатель на член. Вы должны использовать явно & и квалифицированное имя при создании указателя на член.

+0

Это работает, отлично, спасибо. – Jolle

0

Чтобы заставить его работать, чтобы ваши методы static

static void handler1(){}; 
static void handler2(){}; 

Какими бы ни были последствия (read here пожалуйста, для получения более подробной информации), это будет иметь :-(

.
1
void handler1(){} 
void handler2(){} 

являются функции-члены CLI. правильный путь «адрес» их является &CLI::handler1 и не handler1. Однако тогда они не будут приняты void (*h)(void), которые необходимо будет заменить на void (CLI::*h)(void). Но это, вероятно, не то, что вы хотите.

Возможно, подумайте о том, чтобы прочитать о std::function для стирания типа, или сделайте свой handler1/handler2 статическим.

1

Вы должны использовать синтаксис для указателя на член класса вместо синтаксиса для свободного указателя функции.

class CLI; 

struct CLI_Command{ 
    CLI_Command(char* s, void (CLI::*h)(void)){ 
     command_string = s; 
     handler = h; 
    } 

    char* command_string; 
    void (CLI::*handler)(void); 
}; 

Кроме того, убедитесь, что вы вызываете функцию через указатель текущего класса CLI;

void CLI::process(char *cmd) { 
    CLI_Command command* = /* lookup the command */ 
    this->(command->handle)(); 
} 
+0

Вам нужно '-> *' (или '. *') При работе с указателем на член. –

2

В дополнение к другим ответы, еще один вариант заключается в использовании std::function вместе с std::bind():

struct CLI_Command{ 
    ... 
    std::function<void> handler; 
}; 

class CLI { 
    ... 
    CLI_Command cli_table[NO_CLI_COMMANDS] = { 
     { "Command1", std::bind(&CLI::handler1, this) }, 
     { "Command2", std::bind(&CLI::handler2, this) } 
    }; 

    void handler1(){}; 
    void handler2(){}; 
}; 
+0

О, круто. Есть ли у вас представление о том, сколько издержек это принесет? Моя цель - небольшое встроенное устройство, поэтому я не могу позволить себе много накладных расходов :). – Jolle

+0

@Jolle не проблема, это для полноты, поэтому вопрос может быть полезен другим людям. –

+0

на самом деле это был вопрос, потому что я понятия не имею, вызвало ли это какие-либо накладные расходы :) – Jolle