I'm continuously running into the same problem, and can't fix it even when looking through tutorials.
I've "set up" my State machine, but I can't transition between states.
Here is my StateMachine:
class StateMachine
{
State* m_State;
public:
StateMachine();
~StateMachine();
void changeState(State* state);
};
And here is an example State:
class A : State
{
public:
A();
~A();
void handleInput(int a);
}
If I pass a = 1 into A::handleInput() I want to transition to State B. But when I implement it I can't access the StateMachine from A::handleInput(), making me scrub my head in agony.
But when I implement it I can't access the StateMachine from A::handleInput()
Well, that's a well known problem with the State Pattern, that there's no mention how to keep the state classes in track with an enclosing State Machine.
IMO, that's one of the valid use cases to consider the StateMachine class as being implemented as a Singleton.
This way it's instance would be accessible from any Stateclass implementation.
As I'm talking in terms of Design Patterns here, the State classes could be designed with help of the Flyweight Pattern, since they're usually stateless themselves.
I've once driven all that into a c++ template framework, which abstracts the interfaces of State and State Machine (see link below).
Here's a short code example by these means:
StateMachine.h
struct State {
virtual void handleInput(int x) = 0;
virtual ~State() {} = 0;
};
class StateMachine {
State* m_State;
StateMachine();
public:
static StateMachine& instance() {
static StateMachine theInstance;
return theInstance;
}
void changeState(State* state) {
m_State = state;
}
void triggerInput(int x) {
m_State->handleInput(x);
}
};
StateA.h
#include "StateMachine.h"
class StateB;
extern StateB* stateB;
class StateA : public State {
public:
virtual ~StateA() {}
virtual void handleInput(int x) {
if(x == 1) {
// Change to StateB
StateMachine::instance.changeState(stateB);
}
else {
// Do something with x
}
}
};
I omit the definition od StateB here, should be the same manner as StateA.
References:
C++ Singleton Design Pattern
State machine template class framework for C++
I've taken a look at the Sourcemaking example and for me the implementation example really sucks; having to create new instances upon every state change:
https://sourcemaking.com/design_patterns/state/cpp/1
Personally as someone who's designed state machines in electronics with JK flip flops, I would use a similar but semantically different approach. The complexity in state machines involves the action performed according to the state and input; typically in C you would do this with lots of switch statements and possibly arrays describing how to handle the current state and new input aka event.
So to me the OO approach to this would be to model the event handler. This would have an interface which describes the format of the inputs. You then have different implementations of that interface for each different state. With that, the state machine can simply implement a collection of states to event handlers - array, vector or map. Although the handlers still may contain case statements, the overall spaghettiness is very much reduced. You can easily extend the design with new state handlers as and when necessary:
So you could have something like this:
#include <map>
typedef enum
{
//TODO : state list, e.g.
eOff,
eOn
}
teCurrentState;
typedef struct
{
//TODO : Add inputs here, e.g.
bool switch1;
}
tsInputDesc;
typedef struct
{
//TODO : Add outputs here, e.g.
bool relay1;
}
tsOutputDesc;
// ------------------------------------------------
class IEventHandler
{
public:
virtual ~IEventHandler() {}
// returns new state
virtual teCurrentState handleInput(tsInputDesc const& input, tsOutputDesc& output) = 0;
};
// ------------------------------------------------
class OnStateHandler : public IEventHandler
{
public:
virtual teCurrentState handleInput(tsInputDesc const& input, tsOutputDesc& output) override
{
//TODO : IMPLEMENT
teCurrentState newState = TODO....
return (newState);
}
};
// ------------------------------------------------
class OffStateHandler : public IEventHandler
{
public:
virtual teCurrentState handleInput(tsInputDesc const& input, tsOutputDesc& output) override
{
//TODO : IMPLEMENT
teCurrentState newState = TODO....
return (newState);
}
};
// ------------------------------------------------
class StateMachine
{
protected:
teCurrentState mCurrentState;
std::map<teCurrentState, IEventHandler*> mStateHandlers;
void makeHandlers()
{
mStateHandlers[eOff] = new OffStateHandler();
mStateHandlers[eOn] = new OnStateHandler();
}
public:
StateMachine()
{
makeHandlers();
mCurrentState = eOff;
}
void handleInput(tsInputDesc const& input, tsOutputDesc output)
{
teCurrentState newState = mStateHandlers[mCurrentState]->handleInput(input, output);
mCurrentState = newState;
}
};
// ------------------------------------------------
void runFsm()
{
StateMachine fsm;
tsInputDesc input;
tsOutputDesc output;
bool alive = true;
while (alive)
{
// TODO : set input according to....inputs (e.g. read I/O port etc)
fsm.handleInput(input, output);
// TODO : use output
}
}
Related
I'm setting up a State system for my game.
class State
{
protected:
enum State_
{
STATE_INTRO,
STATE_GAME,
STATE_PAUSE,
STATE_CUTSCENE,
};
public:
State();
virtual void run(State_) = 0;
virtual ~State(); // virtual destructor cus we will be inheriting this class
};
I then have inherited classes which represent each state
class IntroState : public State
{
public:
void run(State_ STATE);
};
I want the run function to have different functionality based off of what state the game is in, is it bad practice to achieve that like this:
void IntroState::run(State_ STATE)
{
if (STATE == STATE_INTRO)
{
// load the intro
}
}
I'm not sure how else to do this, thanks (and keep in my mind I'm JUST learning about states so I might be completely off here)
To expand on my comment, here is a possible approach (improvements are appreciated):
class Game {
//... Initialize all State-derived classes in constructor and put them in states (not shown)
vector<unique_ptr>> states;
State_ currentState {STATE_INTRO};
State_ nextState {STATE_INTRO};
public:
void setNextState(State_ state ) {nextState = state;}
void Play() {
for(;;) { //endless loop
if (!states[currentState]->run()) return;//stopping when run returns false
currentState = nextState;
}
}
};
And run could look like this:
class IntroState : public State {
//...
void run(Game& game) {
// do stuff
game.setNextState(STATE_GAME);
return true;
}
};
Of course, you need to figure out the include order, and you'll need to forward-declare Game in State.hpp (the code shown here only shows the central idea). Also, the implementations of run and Play should of course be in seperate .cpp files (didn't do that here so this example wouldn't get too long)
I think you don't need polymorphism in your case since you will only have one State class in your application (correct me if I'm wrong).
You're run function would look like this:
void run(State_ state)
{
switch (state)
{
case STATE_INTRO:
doIntro();
case STATE_BLAH:
doBlah();
// fill all you states...
}
}
void doIntro()
{
// do something for the intro
}
void doBlah()
{
// do something for blah
}
Now if you really wanna get fancy and remove the switch statement:
class State
{
private:
void doA() {}
void doB() {}
enum State_
{
A = 0,
B,
END_
};
std::function<void(void)> functions[END_];
public:
State()
{
functions[A] = std::bind(&State::doA, this);
functions[B] = std::bind(&State::doB, this);
}
void run(State_ state)
{
functions[state]();
}
};
The state pattern
itself is really nice pattern for implementing state machines because it allows to encapsulate state transitions logic in states themselves and adding a new state is actually becomes easier because you need to make changes only in relevant states.
But, it is usually avoided in description how should states be changed.
If you implement state change logic in Context then whole the point of pattern is missed, but if you implement state change logic in states, that means you need to set a new state in Context.
The most common way is to add the public method to Context SetState() and pass reference to Context to the state object, so it will be able to set a new state, but essentially it will allow the user to change state outside the state machine.
To avoid it I came to the following solutions:
class IContext {
public:
virtual void SetState(unique_ptr<IState> newState) = 0;
}
class Context : public IContext {
private:
virtual void SetState(unique_ptr<IState> newState) override { ... };
}
But in general changing the method scope in derived class doesn't look really good.
Is there another way to hide this interface (friend class is not an option because it requires to change the Context class for each state being added)?
You could consider having the handler handle()returning the next state...
class IState {
public:
virtual unique_ptr<IState> handle(Context&) = 0;
};
class StateA : public IState {
private:
// presented inline for simplicity, but should be in .cpp
// because of circular dependency.
//
virtual unique_ptr<IState> handle(Context& ctx) override
{
//...
if (/*...*/)
return make_unique(StateB{});
//... including other state switch..
return { nullptr }; // returning null indicates no state change,
// returning unique_ptr<>(this) is not really an option.
}
};
The goal of the state pattern is to hide/encapsulate different implementations from the caller.However, caller only needs to know what type of implementation it needs.
Not sure how much this helps, but I just implemented a sample state machine in C# that uses the observer pattern and a tiny bit of reflection to get a very clean and encapsulated implementation of the state pattern.
Context.cs:
using System;
using System.Collections.Generic;
using System.Linq;
public class Context
{
State State { get; set; }
List<State> States { get; }
public Context()
{
States = new()
{
new HappyState(),
new SadState(),
};
SetState<HappyState>();
}
void DoSomething() => State?.DoSomething();
string ReturnSomething() => State?.ReturnSomething();
void SetState<StateType>() where StateType : State => SetState(typeof(StateType));
void SetState(Type stateType)
{
if (!stateType.IsSubclassOf(typeof(State))) return;
var nextState = States.Where(e => e.GetType() == stateType).First();
if (nextState is null) return;
if (State is not null)
{
State?.ExitState();
State.ChangeRequested -= OnChangeRequested;
}
State = nextState;
State.ChangeRequested += OnChangeRequested;
State.EnterState();
}
void OnChangeRequested(Type stateType) => SetState(stateType);
}
State.cs:
using System;
public abstract class State
{
public event Action<Type> ChangeRequested;
protected void SetState<StateType>() where StateType : State
{
ChangeRequested?.Invoke(typeof(StateType));
}
public virtual void EnterState() { }
public virtual void ExitState() { }
public virtual void DoSomething() { }
public virtual string ReturnSomething() => "";
}
You can then use this Syntax in either the Context or any State
SetState<HappyState>();
Link to Repository
I have a question regarding inheritance and designing a user interface.
I have a class KeyboardKey which represents an individual keyboard key, such as Q, W, E, R, ... etc.
I have a class Keyboard which contains a vector of class Keyboardkey. [Important!]
I am using SFML, and so each time an event is generated from an event loop, it is sent to the keyboard class. This class then farms that event out to the corresponding key.
In addition, I have a class SynthesizerKey which inherits from KeyboardKey. In addition to the regular key stuff, such as "is the key enabled", "is the key pressed", this class contains data and functions to handle generating a sin wave tone. Variables include the amplitude and current phase of the sin wave.
I am now about to create a class SynthesizerKeyboard. I was about to copy and paste all the code from class Keyboard into this class, however this is not good programming practice, as code is duplicated!
The main issue I have is that SynthesizerKeyboard contains a function to generate a sequence of samples to be stored in a buffer. In order to generate the samples, a loop iterates over each KeyboardKey and checks if it is pressed. If it is, then we must generate a sample corresponding to that keys note/frequency.
However, since the vector contains class KeyboardKey and not class SynthesizerKey I do not have the variables for the phase and amplitude of the sin waves as member data of the elements of the vector.
I think I may have to do what is known as "refactoring" [?], and separate the "sin wave" parts of SynthesizerKey from the KeyboardKey parts. In other words, I ditch the SynthesizerKey class and have an Synthesizer class and a KeyboardKey class, separately. I then have a vector of Synthesizer in class SynthesizerKeyboard in addition to the vector of KeyboardKey in class Keyboard which I have access to in SynthesizerKeyboard through inheritance.
However this is less elegant. Is there another way?
Below is some code which might help the reader understand the quesiton in more detail.
SynthesizerKeyboard
class SynthesizerKeyboard : public Keyboard
{
public:
SynthesizerKeyboard(const sf::Font& sf_font)
: Keyboard(sf_font)
{
}
double Sample() const
{
for(std::vector<KeyboardKey>::iterator it = m_keyboardkey.begin()
it != m_keyboardkey.end(); ++ it)
{
if(it->IsKeyPressed())
{
it->Sample();
}
}
}
void GenerateBufferSamples(std::vector<sf::Int16> buffer)
{
for(std::size_t i = 0; i < buffer.size(); ++ i)
{
buffer[i] = Sample();
}
}
};
SynthesizerKey
class SynthesizerKey : public KeyboardKey
{
protected:
AbstractOscillator *m_abstractoscillator;
public:
double Sample() const
{
return m_abstractoscillator->Sample();
}
};
Keyboard
class Keyboard
{
protected:
std::vector<KeyboardKey> m_keyboardkey;
public:
Keyboard(const sf::Font& sf_font)
void Draw(sf::RenderWindow& window)
void Event(const sf::Event& event)
{
for(std::vector<KeyboardKey>::iterator it = m_keyboardkey.begin();
it != m_keyboardkey.end(); ++ it)
{
(*it).Event(event);
}
}
bool IsKeyPressed(const sf::Keyboard::Key& sf_key)
{
for(std::vector<KeyboardKey>::iterator it = m_keyboardkey.begin();
it != m_keyboardkey.end(); ++ it)
{
if((*it).Key() == sf_key)
{
return (*it).IsKeyPressed();
}
}
}
};
KeyboardKey
class KeyboardKey
{
protected:
KeyState m_keystate;
sf::Color m_pressed_color;
sf::Color m_release_color;
sf::Text m_sf_text;
sf::Keyboard::Key m_sf_keyboard_key;
sf::RectangleShape m_sf_rectangle;
public:
KeyboardKey(const sf::Keyboard::Key& sf_keyboard_key, const std::string& text, const sf::Font& sf_font,
const double position_x, const double position_y)
void Draw(sf::RenderWindow& window)
void Event(const sf::Event& event)
bool IsKeyPressed()
};
Going to skip over the keys for now, but you should consider something similar for them.
First define a bare bones abstract that performs all of the common tasks and includes hooks for the classes that specialize the abstract to fill out to perform their particular behaviour:
class AbstractKeyboard
{
protected:
std::vector<std::unique_ptr<KeyboardKey>> m_keyboardkey;
void Draw();
void Event()
{
for(auto &key: m_keyboardkey)
{
key->Event();
}
}
bool IsKeyPressed(const sf::Keyboard::Key& sf_key)
{
for(auto &key: m_keyboardkey)
{
if(key->isKey(sf_key))
{
return key->IsKeyPressed();
}
}
return false; // need this to handle the no match case, otherwise undefined behaviour
}
void doStuff()
{
// generic keyboard stuff goes here
doSpecificStuff();
}
virtual void doSpecificStuff() = 0;
public:
AbstractKeyboard(const sf::Font& sf_font);
virtual ~AbstractKeyboard();
};
All keyboards have keys, so the vector of keys goes here. Note that we've gone from a vector of keys to a vector of smart pointers to keys. Now we can have any key that inherits the basic key, synthesizer key for example, and the smart pointer eliminates the usual memory woes of dealing with pointers.
The big takeaway here is the doStuff function. It does stuff. What is up to you. When it's done doing the basic stuff that all keyboards must do, it calls doSpecificStuff, a function that each inheritor must fill out, even if it does nothing. doSpecificStuff does whatever the inheritor does differently, add extra behaviours, and generally makes a synthesizer more than just a regular keyboard.
Here is the basic keyboard:
class Keyboard:public AbstractKeyboard
{
protected:
void doSpecificStuff()
{
// Do keyboard Stuff, if there is any specific stuff to do
}
public:
Keyboard(const sf::Font& sf_font): AbstractKeyboard(sf_font)
{
}
};
It doesn't do anything special, but it could but putting special code into doSpecificStuff.
The synthesizer adds a few functions for folk who know it is a synthesizer (Sample and GenerateBufferSamples) as well as implementing doSpecificStuff to do synthesizer stuff.
class SynthesizerKeyboard : public AbstractKeyboard
{
protected:
void doSpecificStuff()
{
// I do specific stuff! Yay me!
}
public:
SynthesizerKeyboard(const sf::Font& sf_font): AbstractKeyboard(sf_font)
{
}
// leaving these as an example of how to get a SynthesizerKey out of m_keyboardkey
double Sample() const
{
// just going to sum because I don't know what's supposed to happen in here
double sum = 0.0;
for(auto &key: m_keyboardkey)
{
if(key->IsKeyPressed())
{
if(SynthesizerKey* skey = dynamic_cast<SynthesizerKey*>(key.get()))
{
sum += skey->Sample();
}
else
{
// like freak out, man.
}
}
}
return sum;
}
void GenerateBufferSamples(std::vector<sf::Int16> buffer)
{
for(sf::Int16 & val: buffer)
{
val = Sample();
}
}
};
Since the synthesizer uses synthesizer keys, Sample contains an example of how to turn a pointer to a regular key into a synthesizer key and trap a configuration error that places the wrong type of key into m_keyboardkey
By adding a virtual destructor and the virtual keyword to Sample in SynthesizerKeyboard, we could also make a
class MoogSynthesizer: public SynthesizerKeyboard
{
public:
double Sample() const override
{
// I do Moog sampling!
}
}
I would like to create a simple framework for throwing and catching events in a game. Events could be things like a Collision which (according to the type) can take several arguments (note that every Event type may take another amount of arguments, not just two as in the example).
I would then like to implement functions/classes/... to deal with a Collision, based on polymorphism. This example should illustrate the problem:
#include <iostream>
#include <vector>
class Entity {};
class Player: public Entity {};
class Bomb: public Entity {
public:
bool exploded;
};
class MineSweeper: public Entity {};
// For now, I only included Collisions, but I eventually want to extend it to
// more types of Events too (base class Event, Collision is derived class)
void onCollision(Player* p, Bomb* b) {
if (! b->exploded) {
std::cout << "BOOM";
b->exploded = true;
}
}
void onCollision(Entity* e, Entity* f) {
std::cout << "Unhandled collision\n";
}
// Possibility for Collision between Minesweeper and Bomb later
class Game {
public:
std::vector<Entity*> board; // some kind of linear board
Game() {
board = {new Player, new Bomb, new MineSweeper};
}
void main_loop() {
onCollision(board[0], board[1]); // player and bomb!
onCollision(board[1], board[2]);
}
};
int main() {
Game g;
g.main_loop();
}
Note that I understand perfectly well why the above code doesn't work as intended, I included this example solely to illustrate my problem better.
The above example uses functions for the events, but I'm perfectly fine with classes or any other solution that is maintainable.
I hope it is clear that I would like C++ to decide which event handler to use based on the types of the arguments (presumably at runtime).
My question: How can I do this in C++? An example would be appreciated.
(not my question: fix my code please)
user2864740 provided enough clues for me to find a solution myself. Multiple dispatch was indeed the missing piece.
The following code works as intended, making use of dynamic_cast to dispatch correctly.
#include <iostream>
#include <vector>
class Entity {
virtual void please_make_this_polymorphic() {}
// although this function does nothing, it is needed to tell C++ that it
// needs to make Entity polymorphic (and thus needs to know about the type
// of derived classes at runtime).
};
class Player: public Entity {};
class Bomb: public Entity {
public:
bool exploded;
};
class MineSweeper: public Entity {};
// For now, I only included Collisions, but I eventually want to extend it to
// more types of Events too (base class Event, Collision is derived class)
void onCollision(Player* p, Bomb* b) {
if (!b->exploded) {
std::cout << "BOOM\n";
b->exploded = true;
}
}
void onCollision(Entity* e, Entity* f) {
std::cout << "Unhandled collision\n";
}
void dispatchCollision(Entity* e, Entity* f) {
Player* p = dynamic_cast<Player*>(e);
Bomb* b = dynamic_cast<Bomb*>(f);
if (p != nullptr && b != nullptr) {
onCollision(p, b); // player and bomb
} else {
onCollision(e, f); // default
}
}
class Game {
public:
std::vector<Entity*> board; // some kind of linear board
Game() {
board = {new Player, new Bomb, new MineSweeper};
}
void main_loop() {
dispatchCollision(board[0], board[1]); // player and bomb
dispatchCollision(board[1], board[2]);
}
};
int main() {
Game g;
g.main_loop();
}
Although it works, I'd like to point out some problems with this code:
Manual editing of dispatchCollision needed when adding new Collisions.
Currently, the dispatcher using a simple kind of rule-based system. (Does it fit rule 1? What about rule 2? ...) When adding loads of different functions it needs to dispatch, that may have an impact on the performance.
A collision between A and B should be the same as a collision between B and A, but that isn't properly handled yet.
Solving these problems is not necessarily in the scope of this question IMHO.
Also, the example given should work just as well for more than 2 arguments. (Multiple dispatch, not just double dispatch.)
You should decide first what event subscription model you need.
It could be signal/slot mechanism and you can find plenty of libraries:
https://code.google.com/p/cpp-events/ , http://sigslot.sourceforge.net/ and the like.
Or it could be bubbling/sinking events like in HTML DOM when event gets propagated on parent/child chain ( from event source element to its containers).
Or even other schema.
It is quite easy to create whatever you need with std::function holders in modern C++.
Maybe a good structure for your case could be something like this:
class Entity{
public:
virtual int getType() = 0;
};
enum EntityTypes {
ACTOR,
BOMB,
MINESWEEPER,
};
class Actor : public Entity{
public:
virtual int getType() {return int(ACTOR);}
void applyDamage() {
std::cout << "OUCH";
}
};
class Bomb : public Entity{
public:
Bomb() : exploded(false) {}
virtual int getType() {return int(BOMB);}
void explode() {
this->exploded = true;
}
bool isExploded() {
return this->exploded;
}
protected:
bool exploded;
};
class MineSweeper : public Entity{
public:
virtual int getType() {return int(MINESWEEPER);}
};
class CollisionSolver {
public:
virtual solve(Entity* entity0, Entity* entity1) = 0;
};
class ActorBombCollisionSolver : public CollisionSolver {
public:
virtual solve(Entity* entity0, Entity* entity1) {
Actor* actor;
Bomb* bomb;
if (entity0->getType() == ACTOR && entity1->getType() == BOMB) {
actor = static_cast<Actor*>(entity0);
bomb = static_cast<Bomb*>(entity1);
}else if (entity1->getType() == ACTOR && entity0->getType() == BOMB) {
actor = static_cast<Actor*>(entity1);
bomb = static_cast<Bomb*>(entity0);
}else {
//throw error;
}
if (!bomb->isExploded()) {
bomb->explode();
actor->applyDamage();
}
}
};
class CollisionDispatcher {
public:
CollisionDispatcher() {
CollisionSolver* actorBombCollisionSolver = new ActorBombCollisionSolver;
this->solvers[ACTOR][BOMB] = actorBombCollisionSolver;
this->solvers[BOMB][ACTOR] = actorBombCollisionSolver;
// this part wouldn't be necessary if you used smart pointers instead of raw... :)
this->solvers[BOMB][MINESWEEPER] = 0;
this->solvers[MINESWEEPER][BOMB] = 0;
this->solvers[ACTOR][MINESWEEPER] = 0;
this->solvers[MINESWEEPER][ACTOR] = 0;
}
void dispatchCollision(Entity* entity0, Entity* entity1) {
CollisionSolver* solver = this->solvers[entity0->getType()][entity1->getType()];
if (!solver) {
return;
}
solver->solve(entity0, entity1);
}
protected:
unordered_map<int, unordered_map<int, CollisionSolver*> > solvers;
};
class Game {
public:
std::vector<Entity*> board; // some kind of linear board
Game() : dispatcher(new CollisionDispatcher)
{
board = {new Player, new Bomb, new MineSweeper};
}
void main_loop() {
dispatcher->dispatchCollision(board[0], board[1]);
dispatcher->dispatchCollision(board[0], board[2]);
dispatcher->dispatchCollision(board[1], board[2]);
}
protected:
CollisionDispatcher* dispatcher;
};
int main() {
Game g;
g.main_loop();
}
This way you can easily add new collision solvers, just define the class, and register t in the CollisionDispatcher constructor.
If you use smart pointers you won't need to set zeroes in the map entries not registered, but if you use raw pointers you have to set them to zero OR use unordered_map::find method instead of just grabbing the solver using operator []
Hope it helps!
I've recently returned to C++ development after a hiatus, and have a question regarding
implementation of the State Design Pattern. I'm using the vanilla pattern, exactly as
per the GoF book.
My problem is that the state machine itself is based on some hardware used as part of
an embedded system - so the design is fixed and can't be changed. This results in a
circular dependency between two of the states (in particular), and I'm trying to
resolve this. Here's the simplified code (note that I tried to resolve this by using
headers as usual but still had problems - I've omitted them in this code snippet):
#include <iostream>
#include <memory>
using namespace std;
class Context
{
public:
friend class State;
Context() { }
private:
State* m_state;
};
class State
{
public:
State() { }
virtual void Trigger1() = 0;
virtual void Trigger2() = 0;
};
class LLT : public State
{
public:
LLT() { }
void Trigger1() { new DH(); }
void Trigger2() { new DL(); }
};
class ALL : public State
{
public:
ALL() { }
void Trigger1() { new LLT(); }
void Trigger2() { new DH(); }
};
// DL needs to 'know' about DH.
class DL : public State
{
public:
DL() { }
void Trigger1() { new ALL(); }
void Trigger2() { new DH(); }
};
class HLT : public State
{
public:
HLT() { }
void Trigger1() { new DH(); }
void Trigger2() { new DL(); }
};
class AHL : public State
{
public:
AHL() { }
void Trigger1() { new DH(); }
void Trigger2() { new HLT(); }
};
// DH needs to 'know' about DL.
class DH : public State
{
public:
DH () { }
void Trigger1() { new AHL(); }
void Trigger2() { new DL(); }
};
int main()
{
auto_ptr<LLT> llt (new LLT);
auto_ptr<ALL> all (new ALL);
auto_ptr<DL> dl (new DL);
auto_ptr<HLT> hlt (new HLT);
auto_ptr<AHL> ahl (new AHL);
auto_ptr<DH> dh (new DH);
return 0;
}
The problem is basically that in the State Pattern, state transitions are made by
invoking the the ChangeState method in the Context class, which invokes the
constructor of the next state.
Because of the circular dependency, I can't invoke the constructor because it's
not possible to pre-define both of the constructors of the 'problem' states.
I had a look at this article, and the template method which seemed to be the ideal solution - but it doesn't compile and my knowledge of templates is a rather limited...
The other idea I had is to try and introduce a Helper class to the subclassed states,
via multiple inheritance, to see if it's possible to specify the base class's constructor
and have a reference to the state subclasse's constructor. But I think that was rather
ambitious...
Finally, would a direct implmentation of the Factory Method Design Pattern be the best way
to resolve the entire problem?
You can define the member functions outside of the class definitions, e.g.,
class DL : public State
{
public:
void Trigger2();
};
inline void DL::Trigger2() { new DH(); }
Define the member functions that rely on later class definitions after those classes are defined. The inline keyword is only necessary if you define the member function outside of the class in the header file.
As an aside, why are you just using new DH() in your functions; you're leaking memory everywhere!