我在尝试了一些简单的状态模式之后,遵循了一些优秀的教程: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;
^
现在,我理解错误涉及指针的转换,但我真的很难看到如何解决它。当我跟随这些人的代码时,我有点期待它的工作,但是因为他正在改变它,并试图强化最佳实践,我没有完整的源代码可以遵循。但是,在我完成本教程的其余部分之前,我认为在此阶段理解代码非常重要。
以下是我创建的代码,试图复制他的状态系统:
#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;
}
为什么我的实施没有编译?
编辑:
因此,为了回应早期的课外辅导,我非常感激,我修改了代码。我首先将它们全部放在单独的文件中,但是对于这么少量的测试代码来说,这比它的价值更麻烦。我只是重写了一个声明类的头文件,然后在.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_;
};
这是.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;
}
我仍然无法让它发挥作用。之前的错误已经消失,但我正在努力访问&#34;介绍&#34;的静态实例。并在基类内部玩。引发的错误是:
/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
我以为我怀疑了!太沮丧了!
我应该补充一点,RustyX提供的答案确实可以编译,但是我必须移动&#34;播放&#34;和&#34;介绍&#34;在类定义之外,我可以不再将它们设置为静态,我相信这很重要,因为我只需要一个实例,我希望它们尽早初始化。
答案 0 :(得分:6)
问题是编译器从上到下读取文件。在包含
的行game.state_ = &GameState::play;
他仍然不知道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) {
}
您可以在类声明中保留一些方法。通常情况下,如果方法很小,可以从内联中受益,并且不会出现这种循环依赖问题。
答案 1 :(得分:3)
在所有类的定义之后,将函数的实现移到之外。
编译器必须完全看到继承的类Playing
和Introduction
,才能知道它们是从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;
}