2010-11-28 10 views
0

私はこれらの2つのファイルを持っていますが、インターフェイス(およびコンパイラ)でこのエラーが表示されます。 .cppファイルに自分のメソッドの全身を定義する必要がありますか?"式にはクラスポインタが必要です" Visual StudioのC++エラー

//GameMatch.h 
#pragma once 
#include "Player.h" 

namespace Core 
{ 
    class GameMatch 
    { 
    private: 
     const static unsigned int MAX_PLAYERS=20; 
     unsigned int m_HumanControlled; 
     Score* m_LastDeclaredScore; 
     Score* m_LastScore; 
     unsigned int m_MaxPlayers; 
     Player* m_Players[MAX_PLAYERS]; 
     unsigned int m_PlayerTurn; 
     inline void NextTurn() { m_PlayerTurn=(m_PlayerTurn+1U)%m_MaxPlayers; } 
    public: 
     GameMatch(void); 
     ~GameMatch(void); 
     void RemovePlayer(Player* _player); 
     inline Player* getPlayingPlayer() { return m_Players[m_PlayerTurn]; } 
    }; 
} 

//Player.h 
#pragma once 
#include "IController.h" 
#include "GameMatch.h" 
#include <string> 
#include <Windows.h> 

using namespace Core::Controller; 
using namespace std; 

namespace Core 
{ 
    class Player 
    { 
    private: 
     IController* m_Controller; 
     unsigned int m_Lives; 
     GameMatch* m_GameMatch; 
     string m_Name; 
     bool m_TurnDone; 
    public: 
     inline void Die() 
     { 
      m_Lives-=1U; 
      if (m_Lives<1) m_GameMatch->RemovePlayer(this);//m_GameMatch is the first error 
     } 
     inline const string& getName() { return m_Name; } 
     inline bool IsPlayerTurn() { return (m_GameMatch->getPlayingPlayer()==this); }//m_GameMatch is the second error 
     virtual void Play()=0; 
     inline Player(GameMatch* _gameMatch,const char* name,unsigned int lives=3) 
     { 
      m_GameMatch=_gameMatch; 
      m_Name=name; 
      m_Lives=lives; 
     } 
     inline void WaitTurn() { while(!IsPlayerTurn()) Sleep(1); } 
     virtual ~Player() 
     { 
      delete m_Controller; 
     } 
    }; 
} 

しかし、あなたが見ることができるように、m_GameMatch ポインタであるので、なぜこのエラー私は多分ヘッダファイルの「再帰含める」のために、理解していません...

UPDATE 1:

//GameMatch.h 
#pragma once 
#include "Score.h" 
#include "Player.h" 

namespace Core 
{ 
    class GameMatch 
    { 
    private: 
     const static unsigned int MAX_PLAYERS=20; 
     unsigned int m_HumanControlled; 
     Score* m_LastDeclaredScore; 
     Score* m_LastScore; 
     unsigned int m_MaxPlayers; 
     Player* m_Players[MAX_PLAYERS]; 
     unsigned int m_PlayerTurn; 
     inline void NextTurn(); 
    public: 
     GameMatch(void); 
     ~GameMatch(void); 
     void RemovePlayer(Player* _player); 
     inline Player* getPlayingPlayer(); 
    }; 
} 

//Player.h 
#pragma once 
#include "IController.h" 
#include "GameMatch.h" 
#include <string> 
#include <Windows.h> 

using namespace Core::Controller; 
using namespace std; 

namespace Core 
{ 
    class Player 
    { 
    private: 
     IController* m_Controller; 
     unsigned int m_Lives; 
     GameMatch* m_GameMatch; 
     string m_Name; 
     bool m_TurnDone; 
    public: 
     inline void Die(); 
     inline const string& getName(); 
     inline bool IsPlayerTurn(); 
     virtual void Play()=0; 
     inline Player(GameMatch* _gameMatch,const char* name,unsigned int lives=3); 
     inline void WaitTurn(); 
     virtual ~Player(); 
    }; 
} 

私はPlayer.hが含まれており、前方GameMatch.h内部このようにクラスを宣言していない場合、これらは今2つのヘッダは、しかし、それは、働いまだありません。 クラスプレーヤー。 しかし、私はいくつかのPlayerメソッドを使いたいのですが、何かを宣言し直す必要があります。これはヘッダファイルの処理ではありませんか?私は多くの場所にヘッダーファイルを含めることができます...なぜこのケースではできませんか?

SOLUTION: はい、あなたが得た答えが正解のようだ: 答えはチャットでAlf P. Steinbachからです。循環ヘッダ依存性が問題となる。他の問題もあるかもしれませんが、循環依存性は大きな問題です。 T *を使用するためにクラスの完全な定義は必要ありません。 そのサイクルの通常の破壊は、あなたがプレーヤー*とプレイヤー&を使用し、さらにメンバ関数を宣言することができるようにだけ、プレイヤーがクラスで、コンパイラに指示します

class Player; 

のようなクラスを、フォワード宣言することです(Playerクラスが完全に定義されるまでこのような関数を定義することはできませんが) 具体的な例として、Core :: GameMatchクラス定義に必要なのはPlayerクラスの前方宣言です。 実装ファイルに "player.h"を含めることができます。 GameMatchの実装に必要な場合は です。 ファイルを小さなボックスとして描画して表示する矢印を描画すると、循環的な依存関係がなくなることがわかります

これは私が得た答えが正しいので、 OJのマークを付けてください

答えて

1

サイクリックヘッダーは絶対に避けてください。

ヘッダーファイルにすべてを入れるのではなく、関数の内容を.cppファイルに分割します。また、毎回#includeものではなく、代わりに宣言してください。

サイクリックインクルードを削除すると、コードが動作する可能性が高くなります。

+0

退屈な...私は試してみるよ、ありがとう –

+3

退屈?私はあなたを興奮させるためにここにいません、私は問題を解決するためにここにいます。解決策が見つからない場合は、より興味深い質問を投稿してください。 –

+0

退屈でない回答...退屈なことをすること、申し訳ありませんが、私はあなたを怒らせたくありません –

関連する問題