views:

266

answers:

2

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;
+1  A: 

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;}
jmucchiello
+5  A: 

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)
{
    ...
}
Adam Rosenfield