状态模式C++

Wil*_*nes 8 c++ virtual state class

我在尝试遵循一些优秀的教程后,试图煽动一个简单的状态模式:http://gameprogrammingpatterns.com/state.html

我正在完成当前教程的一半,我试图通过将它们包含在基类中来复制每个状态的静态实例.但是,当谈到切换状态时,g ++会抛出这个错误.

   state_test.cpp: In member function ‘virtual void Introduction::handleinput(Game&, int)’:
state_test.cpp:55:16: error: cannot convert ‘Playing*’ to ‘GameState*’ in assignment
    game.state_ = &GameState::play;
                ^
Run Code Online (Sandbox Code Playgroud)

现在,我理解错误涉及指针的转换,但我真的很难看到如何解决它.当我跟随这些人的代码时,我有点期待它可以工作,但是因为他正在改变它,并且试图强化最佳实践,我没有完整的源代码可以遵循.但是,在我完成本教程的其余部分之前,我觉得在此阶段理解代码非常重要.

以下是我创建的代码,试图复制他的状态系统:

#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) 
        {
            if (arbitary == 1)
            game.state_ = &GameState::play;
        }

    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) 
        {
            if (arbitary == 0)
            game.state_ = &GameState::intro;
        }

    virtual void update(Game& game) {}
};

int main(int argc, char const *argv[])
{
    Game thisgame;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的实现没有编译的任何想法?

编辑:

因此,为了回应早期的辅导,我非常感激,我修改了代码.我首先将它们全部放在单独的文件中,但是对于这么少量的测试代码来说,这比它的价值更麻烦.我只是重写了一个声明类的头文件,然后在.cpp文件中定义它们.

这是.h文件:

class Introduction;
class Playing;
class Game;
class GameState;

class GameState
{
    public:

    static Introduction intro;
    static Playing play;

    virtual ~GameState();
    virtual void handleinput(Game& game, int arbitary);
    virtual void update(Game& game);

};


class Introduction : public GameState
{
public:

    Introduction();

    virtual void handleinput(Game& game, int arbitary); 

    virtual void update(Game& game);

};

class Playing : public GameState
{
public:
    Playing();

    virtual void handleinput(Game& game, int arbitary);

    virtual void update(Game& game);    
};


class Game
{
public:

    Game();

    ~Game();

    virtual void handleinput(int arbitary);

    virtual void update();

    GameState* state_;

};
Run Code Online (Sandbox Code Playgroud)

这是.cpp文件:

#include <iostream>
#include "state.h"


GameState::~GameState() 
    {std::cout << "Exiting Game State Instance" << std::endl;}
void GameState::handleinput(Game& game, int arbitary) 
    {}
void GameState::update(Game& game) 
    {}



Game::Game()
    {}
Game::~Game()
    {}
void Game::handleinput(int arbitary)
        {
            state_->handleinput(*this, arbitary);
        }

void Game::update()
        {
            state_->update(*this);
        }


Introduction::Introduction()    
    {
        std::cout << "constructed Introduction state" << std::endl;
    }

void Introduction::handleinput(Game& game, int arbitary) 
        {
            if (arbitary == 1)
            game.state_ = &GameState::play;
        }

void Introduction::update(Game& game) {}


Playing::Playing()  
        {
            std::cout << "constructed Playing state" << std::endl;
        }

void Playing::handleinput(Game& game, int arbitary) 
        {
            if (arbitary == 0)
            game.state_ = &GameState::intro;
        }

void Playing::update(Game& game) {}



int main(int argc, char const *argv[])
{
    Game mygame;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我仍然无法让它发挥作用.之前的错误已经消失,但我正在努力访问"引入"的静态实例并在基类内部进行播放.抛出的错误是:

/tmp/ccH87ioX.o: In function `Introduction::handleinput(Game&, int)':
state_test.cpp:(.text+0x1a9): undefined reference to `GameState::play'
/tmp/ccH87ioX.o: In function `Playing::handleinput(Game&, int)':
state_test.cpp:(.text+0x23f): undefined reference to `GameState::intro'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

我以为我怀疑了!太沮丧了!

我应该补充一点,RustyX提供的答案确实可以编译,但是我必须在类定义之外移动"播放"和"介绍"的实例,然后我就不再将它们设置为静态,我相信这很重要因为我只需要一个实例,我希望它们尽早初始化.

mic*_*srb 6

问题是编译器从上到下读取文件.在包含的行

game.state_ = &GameState::play;
Run Code Online (Sandbox Code Playgroud)

他仍然不知道Playing继承自GameState.它只知道这Playing是一个将在稍后声明的类.

您应该从方法实现中拆分类声明.首先是所有类声明,然后是方法实现.在更大的项目中,您可以将它们全部拆分为单独的*.h和*.cpp文件,这种排序自然会发生.

缩短的例子:

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) {
}
Run Code Online (Sandbox Code Playgroud)

您可以在类声明中保留一些方法.通常,如果方法很小,可以从内联中受益,并且没有这种循环依赖性问题.