state pattern C++
The problem is that the compiler reads the file from top to bottom. At the line that contains
game.state_ = &GameState::play;
he still doesn't know that Playing
inherits from GameState
. It only knows that Playing
is a class that will be declared later.
You should split the class declarations from method implementations. Have all class declarations first and method implementations later. In bigger project you would split them all to individual *.h and *.cpp files and this ordering would happen naturally.
Shortened example:
class Playing : public GameState
{
public:
Playing();
virtual void handleinput(Game& game, int arbitary);
virtual void update(Game& game);
};
// Declarations of other classes...
Playing::Playing() {
std::cout << "constructed Playing state" << std::endl;
}
void Playing::handleinput(Game& game, int arbitrary) {
if (arbitary == 0)
game.state_ = &GameState::intro;
}
}
void Playing::update(Game& game) {
}
You can leave some of the method inside the class declaration. Usually it's done if the method is small, would benefit from inlining and doesn't have this kind of circular dependency problem.
Move the implementations of the functions out-of-line to after the definitions of all classes.
The compiler must see the inherited classes Playing
and Introduction
fully before it will know that they inherit from GameState
.
#include <iostream>
class Game;
class Introduction;
class Playing;
class GameState
{
public:
static Introduction intro;
static Playing play;
virtual ~GameState() {std::cout << "an undefined GameState has been destroyed" << std::endl;}
virtual void handleinput(Game& game, int arbitary) {}
virtual void update(Game& game) {}
};
class Game
{
public:
Game()
{}
~Game()
{}
virtual void handleinput(int arbitary)
{
state_->handleinput(*this, arbitary);
}
virtual void update()
{
state_->update(*this);
}
//private:
GameState* state_;
};
class Introduction : public GameState
{
public:
Introduction()
{
std::cout << "constructed Introduction state" << std::endl;
}
virtual void handleinput(Game& game, int arbitary);
virtual void update(Game& game) {}
};
class Playing : public GameState
{
public:
Playing() {std::cout << "constructed Playing state" << std::endl;}
virtual void handleinput(Game& game, int arbitary);
virtual void update(Game& game) {}
};
void Introduction::handleinput(Game& game, int arbitary)
{
if (arbitary == 1)
game.state_ = &GameState::play;
}
void Playing::handleinput(Game& game, int arbitary)
{
if (arbitary == 0)
game.state_ = &GameState::intro;
}
Introduction GameState::intro;
Playing GameState::play;
int main(int argc, char const *argv[])
{
Game thisgame;
return 0;
}