I'm experimenting with state machines and the one that I'm trying to implement uses function pointers to represent states
typedef void (*State)(Signal const&)
class StateMachine
{
public:
void exampleState(Signal const&);
private:
State m_currentState;
}
Basically, I want to derive a separate class for each signal and in each state function the state machine must be able to determine which kind of signal has been received and execute the corresponding code. A solution that I came up with is something like
class Signal {};
class MySignal: public Signal {};
void StateMachine::exampleState(Signal const& signal){
if (typeid(signal) == typeid(MySignal)){
//code here
}
// other cases...
}
First of all I'm not sure that using typeid this way is good practice. Also, this only works if Signal has at least one virtual function.
Another solution would be to define a sort of type flag like an enum, and pass the corresponding one in the derived signal constructor
enum signalType{
mySignalType
//other types
}
class Signal {
public:
Signal(signalType sig_type):m_type(sig_type){};
const signalType m_type;
};
class MySignal: public Signal {
public:
MySignal():Signal(mySignalType){};
};
void StateMachine::exampleState(Signal const& signal){
switch (signal.m_type){
case mySignalType:
//code here
break;
// other cases...
}
}
althoug this requires the enum to be extended each time a new signal class is written.
Is there a more elegant way of achieving this? Or maybe another technique that avoids this check at all? I remember having this problem in other scenarios as well, that's why the question in the title is more general than the example above.
Use dynamic_cast
instead of typeid
:
class Signal {
public:
virtual ~Signal() {}
};
class MySignal: public Signal {};
void StateMachine::exampleState(Signal const& signal){
if (dynamic_cast<MySignal const *>(&signal)){
//code here
}
// other cases...
}