Monday, March 7, 2011

Cannot compile FSM sample code

There is a nice state machine tutorial called UML Tutorial: Finite State Machines by Robert C. Martin. But I can't compile the sample code it provides. I got *FsmTest.cpp(46) : error C2664: 'SetState' : cannot convert parameter 1 from 'class UnlockedState *' to 'class TurnstileState '

Please, help. Thanks.

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;
From stackoverflow
  • Most likely this is because it does not know UnlockedState is a subclass of TurnstileState yet. Remove the function from inside the class to the end of the file:

    class TurnstileFSM {
        void SetState(TurnstileState* s);
    };
    
    void TurnstileFSM::SetState(TurnstileState* s) {itsState = s;}
    
  • The problem is that when you try to call SetState() inside of LockedState::Coin(), the class UnlockedState is an incomplete type: it has been declared but not defined. In order to fix it, you'll need to move the definition of of Coin() to after that of UnlockedState:

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

0 comments:

Post a Comment