2016-08-29 71 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; 
} 

任何想法,爲什麼我的實現不是編制?

編輯:

所以響應早前輔導,對此我很感激,我修改了代碼。我首先將它們全部放在單獨的文件中,但這比測試代碼量小的代價更麻煩。我簡單地重寫了一個聲明類的頭文件,然後在.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; 
} 

而且我仍然無法得到它的工作。之前的錯誤已經消失,但我正在努力訪問「引入」的靜態實例並在基類內部進行遊戲。拋出的錯誤是:

/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提供的答案確實會編譯,但是我必須將「播放」和「引入」的實例移到類定義之外,然後我不能再將它們設置爲靜態的,我相信這很重要,因爲我只需要每個實例的一個實例,我希望它們儘早初始化。

+0

您可能對我的[STTCL](https://github.com/makulik/sttcl)框架感興趣。 –

回答

6

問題是編譯器從上到下讀取文件。在包含

game.state_ = &GameState::play; 

行,他仍然不知道從GameStatePlaying繼承。它只知道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; 
}