У меня два вопроса: первый — о причине конкретной ошибки, которую я пытаюсь здесь решить, второй — о правильности моего подхода к проблеме.
Я пытаюсь создать конечный автомат, который использует указатели на функции-члены, и я теряюсь в деталях. Другое Q / Как и в теме указателя на функцию-член, похоже, имеет дело с вызовом функций-членов извне класса и выступает за использование std :: function и std :: bind. Я тоже читаю C ++ FAQ по указателям на функции-члены который также приводит примеры вызова функций-членов вне класса. Я не совсем уверен, что эти примеры применимы к тому, что я пытаюсь сделать.
Этот подход конечного автомата является общим для всего, что я пытаюсь сделать для этого встроенного приложения (это первое реальное приложение, которое я написал на C ++. Если этот подход глуп, пожалуйста, помогите мне найти лучшее решение.). Ниже приведен конкретный код для класса MessageHandler. Идея состоит в том, что каждый аппаратный коммуникационный порт ISR будет копировать свое содержимое в свой собственный буфер, а затем помещать в очередь свой собственный объект MessageHandler для обработки. Существует несколько интерфейсов связи, но протокол для них одинаков.
Некоторые фрагменты из MessageHandler.h:
class MessageHandler
{
private:
enum state_t {
WAIT_METADATA,
WAIT_PAYLOAD,
NUM_STATES
};
enum transfer_t {
INPUT_PARTIAL_METADATA,
INPUT_METADATA,
INPUT_PARTIAL_PAYLOAD,
INPUT_COMMAND,
INPUT_TIMEOUT,
INPUT_UNKNOWN,
NUM_TRANSFER_INPUTS
};
typedef transfer_t (MessageHandler::*transferFunction)();
transferFunction transferFunctionTable[NUM_STATES] = {
checkMetadata,
checkPayload
};
typedef state_t(MessageHandler::*stateFunction)();
stateFunction stateFunctionTable[NUM_TRANSFER_INPUTS] = {
gotPartialMetadata,
gotMetadata,
gotPartialPayload,
gotCommand,
gotTimeout,
gotUnknownError
};
size_t processTable[NUM_TRANSFER_INPUTS][NUM_STATES] = {
{ 0, 5 },
{ 1, 5 },
{ 5, 2 },
{ 5, 3 },
{ 4, 4 },
{ 5, 5 }
};
...
state_t state;
transfer_t getInput();
transfer_t checkMetadata();
transfer_t checkPayload();
state_t gotPartialMetadata();
state_t gotMetadata();
state_t gotPartialPayload();
state_t gotCommand();
state_t gotTimeout();
state_t gotUnknownError();
...
public:
...
state_t process();
};
И несколько примеров из MessageHandler.cpp:
MessageHandler::transfer_t MessageHandler::getInput()
{
...
return transferFunctionTable[state]();
}
Еще один из MessageHandler.cpp:
MessageHandler::state_t MessageHandler::process()
{
do {
state = stateFunctionTable[ processTable[getInput()][state] ]();
} while (cbRemaining > 0);
}
Я не понимаю, почему для двух предоставленных мной функций-членов я получаю ошибки при вызовах таблицы функций:
Error: expression preceding parentheses of apparent call must have (pointer-to-) function type
Разве это не то, что я предоставил? То есть, как типы TransferFunctionTable и stateFunctionTable не являются указателями на функции?
Я думаю, чтобы исправить это, я должен сделать все функции статичными и передать ссылки / указатели на объект MessageHandler.
Заранее спасибо за помощь.
MessageHandler::transfer_t MessageHandler::getInput()
{
return transferFunctionTable[state]();
}
должно быть
MessageHandler::transfer_t MessageHandler::getInput()
{
return (this->*transferFunctionTable[state])();
}
Ты имел ввиду:
MessageHandler::state_t MessageHandler::process()
{
do {
stateFunction stateAction = stateFunctionTable[ processTable[getInput()][state] ];
state = (this->*stateAction)();
} while (cbRemaining > 0);
}
Указатель на член должен быть разыменован с помощью .*
или же ->*
, Вы не можете просто применить оператор вызова функции к нему.
Кроме того, у вас есть проблема с инициализацией вашего массива. Это должно быть
transferFunction transferFunctionTable[NUM_STATES] = {
&MessageHandler::checkMetadata,
&MessageHandler::checkPayload
};
потому что голое имя функции-члена не превращается в указатель на член. Вы должны использовать адрес оператора &
на квалифицированное имя.
Конечно, оба эти исправления необходимо применить к обеим таблицам указателей на функции-члены.