У меня есть два вопроса: первый по причине конкретной ошибки, которую я пытаюсь решить здесь, второй по правильности моего подхода к проблеме.
Я пытаюсь создать конечный автомат, который использует указатели функций-членов, и я потерян в деталях. Другие вопросы о Q/As в тексте-элементе-члене, похоже, связаны с вызовом функций-членов из-за пределов класса и защищают использование std :: function и std :: bind. Я также читал FAQ C++ по указателям на функции-члены, которые также приводят примеры вызова функций-членов вне класса. Я не совсем уверен, что эти примеры относятся к тому, что я пытаюсь сделать.
Этот подход с государственным компьютером является общим для всего, что я пытаюсь сделать для этого встроенного приложения (это первое реальное приложение, которое я написал в 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
таблицы функций: Error: expression preceding parentheses of apparent call must have (pointer-to-) function type
Разве это не то, что я предоставил? То есть, как типы transferFunctionTable и stateFunctionTable не указывают на функции?
Я думаю, чтобы исправить это, я должен сделать все функции static и передать ссылки/указатели на объект 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
};
потому что голое имя функции-члена не распадается на указатель-на-член. Вы должны использовать адрес-оператора &
по квалифицированному имени.
Конечно, обе эти исправления должны применяться к обеим таблицам указателей на функции-члены.
state = (this->*stateFunctionTable[ processTable[getInput()][state] ])();
, Разве typedef для TransferFunction не должен явно указывать указатель как указатель на функцию-член? Кажется, работает без него.