2016-08-29 13 views
7

私はここに優れたチュートリアルのいくつかを以下の後、簡単な状態パターンを扇動しようとしています:http://gameprogrammingpatterns.com/state.html状態パターンC++

私はこの現在のチュートリアルを途中だ、と私はの静的インスタンスを複製しようとしています基本クラス内にそれらを格納することによって、各状態しかし、状態の切り替えに関しては、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; 
} 

後、私は、作成したコードは、彼の状態のシステムを複製しようとしていますか?

EDIT:

は、だから私はとても感謝していたたため、以前の指導に応答して、私は、コードを修正しました。私はそれをすべて別々のファイルに入れることから始めますが、これはそのような少量のテストコードの価値よりも面倒です。クラスを宣言したヘッダーファイルを1つだけ書き直し、.cppファイルで定義しました。

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; 
} 

そして、私はまだそれが仕事を得ることができない。ここ

は.hファイルです。以前のエラーはなくなりましたが、私は "イントロダクション"の静的インスタンスにアクセスし、ベースクラスの内部でプレーするのに苦労しています。スローされたエラーは次のとおりです。

/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が提供する答えはコンパイルされますが、 "再生"と "導入"のインスタンスをクラス定義の外に移動する必要があります。私がそれぞれのインスタンスを1つだけ必要とするため、これが重要であると考えてください。可能な限り早く初期化したいと考えています。

+0

私の[STTCL](https://github.com/makulik/sttcl)フレームワークに興味があるかもしれません。 –

答えて

6

問題は、コンパイラがファイルを上から下に読み込むことです。

game.state_ = &GameState::play; 

を含む行で、彼はまだPlayingGameStateから継承していることを知りません。 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) { 
} 

あなたは、クラス宣言内のメソッドの一部を残すことができます。通常、メソッドが小さければインライン展開の恩恵を受け、この種の循環依存性の問題は発生しません。

+0

これは自信を持って私の質問に答えているようだ!ありがとう! –

3

すべてのクラスの定義の後に、関数の実装をに移動します。

コンパイラは、継承されたクラスPlayingIntroductionを完全に理解してから、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; 
} 
関連する問題