Не удается скомпилировать образец кода FSM

Есть хороший учебник по конечному автомату под названием Учебное пособие по UML: конечные автоматы Роберта К. Мартина. Но я не могу скомпилировать предоставленный образец кода. Я получил * FsmTest.cpp (46): ошибка C2664: 'SetState': невозможно преобразовать параметр 1 из 'class UnlockedState *' в 'class TurnstileState '

Пожалуйста помоги. Спасибо.

class Turnstile
{
public:
    virtual void Lock();
    virtual void Unlock();
    virtual void Thankyou();
    virtual void Alarm();
};

class TurnstileFSM;
class LockedState;
class UnlockedState;

class TurnstileState
{
public:
    virtual void Coin(TurnstileFSM*) = 0;
    virtual void Pass(TurnstileFSM*) = 0;
protected:
    static LockedState lockedState;
    static UnlockedState unlockedState;
};

class TurnstileFSM : public Turnstile
{
public:
    void SetState(TurnstileState* s) {itsState = s;}
    void Coin() {itsState->Coin(this);}
    void Pass() {itsState->Pass(this);}


private:
    TurnstileState *itsState;
};

class LockedState : public TurnstileState
{
public:
    virtual void Coin(TurnstileFSM* t)
    {
        t->SetState(&unlockedState);
        t->Unlock();
    }
    virtual void Pass(TurnstileFSM* t)
    {
        t->Alarm();
    }
};

class UnlockedState : public TurnstileState
{
public:
    virtual void Coin(TurnstileFSM* t)
    {
        t->Thankyou();
    }
    virtual void Pass(TurnstileFSM* t)
    {
        t->SetState(&lockedState);
        t->Lock();
    }
};

LockedState TurnstileState::lockedState;
UnlockedState TurnstileState::unlockedState;

О, "конечный автомат". Я думал, вы имели в виду "Летающий спагетти-монстр". :-)

Paul Tomblin 22.12.2008 23:28
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
787
3

Ответы 3

Скорее всего, это потому, что он еще не знает, что UnlockedState является подклассом TurnstileState. Удалите функцию из класса до конца файла:

class TurnstileFSM {
    void SetState(TurnstileState* s);
};

void TurnstileFSM::SetState(TurnstileState* s) {itsState = s;}

Проблема в том, что когда вы пытаетесь вызвать SetState() внутри LockedState::Coin(), класс UnlockedState является неполный тип: это был объявлен, но не определенный. Чтобы исправить это, вам нужно переместить определение Coin() после определения UnlockedState:

class LockedState : public TurnstileState
{
public:
    virtual void Coin(TurnstileFSM* t);
    ...
};

class UnlockedState : public TurnstileState
{
    ...
};

void LockedState::Coin(TurnstileFSM* t)
{
    ...
}

В этом примере сгенерированный код должен включать в себя tscontext.h, а класс TurnStyle является производным от контекста, который должен быть объявлен в * tscontext.h "как класс TurnStyleContext.

В моем случае сгенерированный код выглядит так:

    #include "tscontext.h"   // the header file name for the context class"

    // Forward Declarations

    class TurnStyle;

    //----------------------------------------------
    // TurnStyleState: The base state class
    //----------------------------------------------
    class TurnStyleState
    {
      public: 
        virtual const char* StateName() const = 0;
        virtual void Coin( TurnStyle& );
        virtual void Pass( TurnStyle& );
    };

    //----------------------------------------------
    // State: Unlocked
    //----------------------------------------------
    class TurnStyleUnlockedState : public TurnStyleState
    {
      public: 
        virtual const char* StateName() const
            { return "Unlocked"; }
        virtual void Pass( TurnStyle& );
        virtual void Coin( TurnStyle& );
    };
    //----------------------------------------------
    // State: Locked
    //----------------------------------------------
    class TurnStyleLockedState : public TurnStyleState
    {
      public: 
        virtual const char* StateName() const
            { return "Locked"; }
        virtual void Coin( TurnStyle& );
        virtual void Pass( TurnStyle& );
    };
    //----------------------------------------------
    // TurnStyle: The Finite State Machine class
    //----------------------------------------------
    class TurnStyle: public TurnStyleContext
    {
      public: 
        // Static State variables
        static TurnStyleUnlockedState Unlocked;
        static TurnStyleLockedState Locked;

        TurnStyle(); // default Constructor

        // Event functions
        virtual void Coin() { itsState->Coin( *this ); }
        virtual void Pass() { itsState->Pass( *this ); }

        // State Accessor functions
        void SetState( TurnStyleState& theState ) { itsState = &theState; }
        TurnStyleState& GetState() const { return *itsState; }

        const char* GetCurrentStateName() const { return itsState->StateName(); }
        const char* GetVersion() const;

      private: 
        TurnStyleState* itsState;
    };

с конечным автоматом, определенным таким образом:

Context TurnStyleContext     // the name of the context class
FSMName TurnStyle            // the name of the FSM to create
Initial Locked               // the name of the initial state
                             // for C++ output
pragma Header  tscontext.h"   // the header file name for the context class, note the necessary "
{
    Locked
    {
        Coin     Unlocked    Unlock
        Pass     Locked      Alarm
    }
    Unlocked <BeforeUnlocked >AfterUnlocked
    {
        Coin    Unlocked    Thankyou
        Pass    Locked      Lock
    }
}

Контекст реализует FSMError, Thankyou, Lock, Alarm, Unlock, BeforeUnlocked, AfterUnlocked

Другие вопросы по теме