Передать аргумент в функцию, принимающую аргумент родительского класса без приведения аргумента к родительскому классу - PullRequest
0 голосов
/ 20 декабря 2018

Я создаю конечный автомат Boost.Мое состояние имеет указатель на свой собственный бэкэнд (fsm) для обработки событий.Все события моего конечного автомата являются детьми класса MySatetMachineEvent (с примером ребенка, например EventChild).Переходы между состояниями определены только для детей, например, EventChild из MySTateMachineEvent.
Чтобы очистить мой код, я хочу создать функцию processEvent(MySatetMachineEvent event), принимающую все возможные события.Этот класс должен затем вызвать функцию process_event() с переданным событием.Например:

processEvent(MyStateMachineEvent event)
{
    fsm.process_event(event);
}
processEvent(EventCild());

должен вызывать вызов

fsm.process_event(EventChild());

Создание такой функции вызывает ошибку, что fsm.process_event() вызывается с экземпляром MyStateMachineEvent.Как написано выше, для этого случая не определены переходы состояний.

Очевидно, это мешает моему конечному автомату работать должным образом.


Так что мой вопрос: есть лиспособ передачи любого EventChild или другого потомка MyStateMachineEvent в мою функцию processEvent(MySTateMachineEvent event) без приведения переданного объекта к MyStateMachineEvent.


Мне известно о решении перегрузить мою функцию, например

processEvent(EventChild event) {
    fsm.process_event(event);
}

Это может привести к тому, что в моем случае могут функционировать (с точно такой же строкой кода внутри), поэтому я ищу более чистое и более причудливое решение.

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

Хотя мне нравится Vittorio Romeo шаблонный подход , он может не подойти, если у вас, например, есть какая-то очередь событий, содержащая произвольные события.Полиморфный подход может быть более подходящим, чем:

class MyStateMachineEvent
{
public:
    virtual ~MyStateMachineEvent() { }
    virtual void doOrGetSomething() = 0;
};

class EventChild : public MyStateMachineEvent
{
public:
    void doOrGetSomething() override;
};

Теперь ваша функция processEvent может принимать ссылку, также как и вариант fsm:

void processEvent(MyStateMachineEvent& event)
{
    fsm.processEvent(event);
}

void FSM::processEvent(MyStateMachineEvent& event)
{
    // ...
    event.doOrGetSomething();
    // ...
}

И использование может выглядеть так:

std::queue<std::unique_ptr<MyStateMachineEvent>> events;

events.emplace(new EventChild());

processEvent(**events.front());
events.pop();
0 голосов
/ 20 декабря 2018

Вы можете использовать шаблон функции:

template <typename Event>
void processEvent(Event event)
{
    fsm.process_event(event);
}

Каждый экземпляр будет сохранять точный тип аргумента event, который был передан.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...