2016-02-08 46 views
1

我試圖在我的遊戲中爲不同的屏幕創建一個狀態引擎。 id開始屏幕,可能是將來的文件選擇器,overworld地圖,菜單屏幕等。但是當我轉發聲明類時,它說沒有構造函數。類沒有構造函數的前向聲明

GameState.h:

#pragma once 

class GameState 
{ 
public: 
    virtual ~GameState() {} 
    virtual void Update() {} 
    virtual void HandleEvents() {} 
    virtual void Draw(Graphics& gfx) {} 

    GameState* getCurrentState() 
    { 
     return currentState; 
    } 
    void ChangeState(GameState* state) 
    { 
     currentState = state; 
    } 

protected: 
    SDL_Renderer* renderer; 
    GameState* currentState; 
}; 

GameStates.h

#pragma once 
#include "GameState.h" 
#include "Texture.h" 
#include "Keyboard.h" 

class TitleGameState; 
class IntroGameState : public GameState 
{ 
public: 
    IntroGameState(SDL_Renderer* renderer, KeyboardClient& kbd) 
     : 
     kbd(kbd) 
    { 
     background = new Texture("red.png", renderer); 
     this->renderer = renderer; 
    } 
    ~IntroGameState() {} 
    void HandleEvents() 
    { 
     while (!kbd.KeyEmpty()) 
     { 
      KeyEvent e = kbd.ReadKey(); 
      switch (e.GetCode()) 
      { 
      case SDLK_RETURN: 
       if (e.IsPress()) 
       { 
        currentState = new TitleGameState(renderer, kbd); 
       } 
       break; 
      } 
     } 
    } 
    void Logic() {} 
    void Draw(Graphics& gfx) 
    { 
     background->Draw(0, 0, gfx); 
    } 

private: 
    Texture* background; 
    KeyboardClient& kbd; 
}; 

class TitleGameState : public GameState 
{ 
public: 
    TitleGameState(SDL_Renderer* renderer, KeyboardClient& kbd) 
     : 
     kbd(kbd) 
    { 
     background = new Texture("blue.png", renderer); 
    } 
    ~TitleGameState() {} 
    void HandleEvents() 
    { 
     while (!kbd.KeyEmpty()) 
     { 
      KeyEvent e = kbd.ReadKey(); 
      switch (e.GetCode()) 
      { 
      case SDLK_RETURN: 
       if (e.IsPress()) 
       { 
        printf("OK"); 
       } 
       break; 
      } 
     } 
    } 
    void Logic() {} 
    void Draw(Graphics&gfx) 
    { 
     background->Draw(0, 0, gfx); 
    } 

private: 
    Texture* background; 
    KeyboardClient& kbd; 
}; 

我定義的類權之後,我知道我可以只移動它上面IntroGameState,但是當我執行菜單遊戲狀態,它將在菜單狀態和超世界狀態之間來回切換。我怎樣才能解決這個問題?

編譯器錯誤:

error C2514: 'TitleGameState' : class has no constructors 
File: gamestates.h 
Line: 28 

線28是這行代碼:

currentState = new TitleGameState(renderer, kbd); 
+0

請提供1)確切的錯誤消息,並附上行號2)出現錯誤的相關代碼段3)決定您希望我們解決的問題:a)編譯錯誤或b)來來回回。 – iksemyonov

+0

用這些類的完整代碼和編譯器錯誤編輯它。 – Vince

+0

你知道編譯器如何從上到下處理你的代碼嗎? – immibis

回答

2

的錯誤就行了currentState = new TitleGameState(renderer, kbd);是因爲編譯器目前還沒有看到對類的構造函數。它不知道如何編譯這段代碼。

如果你轉發宣告類class TitleGameState;所有你可以聲明的幾乎是一個指針TitleGameState*

要編譯您的代碼,您需要在使用之前定義類。注意:定義類並不意味着定義所有的方法。類定義由方法和成員聲明組成。

class TitleGameState : public GameState 
{ 
public: 
    TitleGameState(SDL_Renderer*, KeyboardClient&); 
    ~TitleGameState(); 
    void HandleEvents(); 
    // ... 
}; 

class IntroGameState : public GameState 
{ 
    // ... 
} 

在定義了類之後,就可以定義成員函數了;

/*inline*/ void TitleGameState::HandleEvents() 
// inline is needed if the method is defined in a header file 
// to help avoid linker errors 
{ 
    // ... 
} 
+0

那麼,把它分成一個頭文件和一個cpp文件?我試圖避免所有這一切,但如果這是我必須做的...... lol – Vince

+0

如果你不想在文件間分割,你不必將它們分開。但是代碼需要被構建,就好像它在哪裏分離一樣。如果方法定義位於頭文件中,請添加'inline'以避免鏈接器錯誤 – Niall

+0

我稍後將要分割它,但是因爲我現在只是測試代碼,所以我試圖避免它。我發現分解代碼使得閱讀和遵循更容易。 – Vince