patterncppMinor
Designing simple state machine in C++
Viewed 0 times
machinesimpledesigningstate
Problem
I have designed a simple state machine for the following diagram:
I am seeking improvements from the community. I especially don't like two things:
For simplicity everything is added in one .cpp file:
```
#include
#include
#include
typedef enum {
Idle,
Start,
Stop,
ChangeSpeed
}State;
class Engine
{
public:
typedef enum {
SetSpeed,
Halt
}Action;
typedef void (Engine::*DoAction)(void);
Engine() {
std::cout StateDiagram;
StateMachine(Engine &engine):engine_(engine) {
stateDiag_[StateAction(Idle, Engine::SetSpeed)] = Start;
stateDiag_[StateAction(Start, Engine::SetSpeed)] = ChangeSpeed;
stateDiag_[StateAction(ChangeSpeed, Engine::SetSpeed)] = ChangeSpeed;
stateDiag_[StateAction(ChangeSpeed, Engine::Halt)] = Stop;
stateDiag_[StateAction(Start, Engine::Halt)] = Stop;
//
// current state is initialized to Idle
//
currentState_ = Idle;
std::cout << "State machine initial state: " << currentState_ << std::endl;
}
void performAction(ActionCallback actionCallback) {
//
// The state machine "state" is: currentState
//
StateAction stateAction(currentState_, actionCallback.action);
if (stateDiag_.find(stateAction) == stateDiag_.end()) {
//
// Invalid state transition
//
std::cout << "You cannot perform action: "
<< actionCallback.action
<< " from state: "
<< currentState_
<< ", invalid transition!!!"
<< std::endl;
return;
}
State oldState = currentState_;
//
// Execute the action and update the state machine
//
(engine_.*actionCallback.callback)();
currentS
I am seeking improvements from the community. I especially don't like two things:
- When calling
performActionI wan't to send only the action without the callback.
- And maybe remove the
Actionenumfrom theEngineclass.
For simplicity everything is added in one .cpp file:
```
#include
#include
#include
typedef enum {
Idle,
Start,
Stop,
ChangeSpeed
}State;
class Engine
{
public:
typedef enum {
SetSpeed,
Halt
}Action;
typedef void (Engine::*DoAction)(void);
Engine() {
std::cout StateDiagram;
StateMachine(Engine &engine):engine_(engine) {
stateDiag_[StateAction(Idle, Engine::SetSpeed)] = Start;
stateDiag_[StateAction(Start, Engine::SetSpeed)] = ChangeSpeed;
stateDiag_[StateAction(ChangeSpeed, Engine::SetSpeed)] = ChangeSpeed;
stateDiag_[StateAction(ChangeSpeed, Engine::Halt)] = Stop;
stateDiag_[StateAction(Start, Engine::Halt)] = Stop;
//
// current state is initialized to Idle
//
currentState_ = Idle;
std::cout << "State machine initial state: " << currentState_ << std::endl;
}
void performAction(ActionCallback actionCallback) {
//
// The state machine "state" is: currentState
//
StateAction stateAction(currentState_, actionCallback.action);
if (stateDiag_.find(stateAction) == stateDiag_.end()) {
//
// Invalid state transition
//
std::cout << "You cannot perform action: "
<< actionCallback.action
<< " from state: "
<< currentState_
<< ", invalid transition!!!"
<< std::endl;
return;
}
State oldState = currentState_;
//
// Execute the action and update the state machine
//
(engine_.*actionCallback.callback)();
currentS
Solution
That's typically how C enums are written, but it's done differently in C++. The
typedef keyword is no longer needed, and the name is given after the enum keyword.enum State {
Idle,
Start,
Stop,
ChangeSpeed
};Code Snippets
enum State {
Idle,
Start,
Stop,
ChangeSpeed
};Context
StackExchange Code Review Q#51067, answer score: 6
Revisions (0)
No revisions yet.