0
votes

Let's say I have been implementing a state machine in the C++ based on the switch statement i.e. I have following piece of code

class StateMachine {
public:

   enum class State {
    State_A,
    State_B,
    State_C
   };

   enum class Event {
    Event_Default,
    Event_A,
    Event_B,
    Event_C
   };

   StateMachine();
   void handleEvent(Event e);
   
private:
   State state;

   void doStateA();
   void doStateB();
   void doStateC();
};

StateMachine::StateMachine() 
{
   state = State::State_A;
}
    
void StateMachine::handleEvent(Event e)
{
   switch (state) 
   {
      case State::State_A:
        doStateA(e);
      break;
      case State::State_B:
        doStateB(e);
      break;
      case State::State_C:
        doStateC(e);
      break;
   }
}

void StateMachine::doStateA(Event e)
{
  // once upon entry into the state do some actions here
  // the actions have to be done only once after state entry
  switch(e) {
    case Event::Event_Default:
    break;
    
    case Event::Event_A:
      state = State::State_B;
    break;

    case Event::Event_B:
      state = State::State_C;
    break;

    case StateMachine::Event::Event_C:
      state = State::State_A;
    break;
  }
}
   
void StateMachine::doStateB(Event e)
{
  // ...
}
   
void StateMachine::doStateC(Event e)
{
  // ...
}

I have found that I need to have the ability to do some actions once upon entry into the states. Of cource I could do those entry actions before the state transitions in the doStateX() methods. But I see following disadvantage of this approach. The entry action of a given state isn't done in that state but in the state (or states) from which the transition occurs. This approach seems to me to be error prone. So I have been looking for a solution where the entry action of a given state is localized directly in that state. Does anybody have any idea?

Are you looking to run a method before leaving a state? - Farid Fakhry
Instead of enums, create a single abstract class with a virtual void doMagic()=0;. The enum values become different subclasses that implement doMagic(). A transition gets specified by specifying the base class (of, likely, subclasses instantiated in static scope). The transition calls doMagic(). Abracadabra? - Sam Varshavchik
@FaridFakhry thank you for your reaction. I have been looking for a solution where the entry action method is invoked only at first entry into a state. - Steve
I think the best way is to use GoF's state pattern. that does bring overhead to your code. If you wanted to avoid overhead what I would do is either use abstraction like @SamVarshavchik said, or create a method "changeState(State state)" that calls the function you wanna run and then switches the state. - Farid Fakhry
@SamVarshavchik thank you for your reaction. As far as I understand correctly your idea you are heading to the State design pattern. I have taken that approach also into account but I have been discouraged by the fact that for the state transition I need to dynamically create instance of the class representing the state into which the transition occurs. Do you have any idea how to avoid the dynamic allocation in case of the State design pattern is used? - Steve