1

たとえば、Player、Bot、Game の 3 つのクラスを持つ小さな Computergame があります。

プレーヤーには、プレーヤーがボットと衝突するかどうかをチェックするメソッドがあります

// Player.h
#include Game.h   
#include Bot.h

class Player {
    private:
    bool collision(Game g)  {

       for (Bot bot: g.bots)
       ...
     }

};

Bot.h (シンプルに保たれていますが、実際の位置やこれまでのようないくつかの他の属性があります)

// Bot.h


class Bot {
    public:
    Bot()
};

ゲームクラスは、ゲームループとボットのリストを処理します

//Game.h
#include Bot.h    
#include Player.h

class Game {

public:
Player player:
std::vector<Bot> bots
void loop() { player.collision() }

};

ここで、Game.h に Player.h が含まれているという問題があり、その逆もあります。

どうすればこれを解決できますか?

4

4 に答える 4

3

ここでの他の回答は確かに技術的に正しいですが、このような状況に遭遇するたびに、私の設計の潜在的な欠陥を指摘しているように見えます. あなたが持っているのは、次のような循環依存関係です。

ここに画像の説明を入力

これは実装の問題だけではありません。クラス間の結合が多すぎるか、逆に情報隠蔽が少なすぎることを意味します。これは、たとえば、 を とはPlayer独立して設計できないことを意味します。Game

したがって、可能であれば、Gameコントローラーが他のクラスに委任するため、このような状況が望ましいと思います。

ここに画像の説明を入力

これを行う 1 つの方法は、が必要なGameときに独自のプロパティへの参照を渡すことです。Player

たとえば、`Game ではなくパラメータをcollision取ります。bots

bool collision(const std::vector<Bot&> bots)  {
    // note pass objects by const ref is usu preferred in C++ to pass by value

   for (Bot bot: g.bots)
   ...
 }

(より洗練されたアプローチでは、インターフェイス、つまり抽象的なベースクラスを自体に渡すことができます)。

他のすべてが失敗した場合は、前方宣言の使用に戻ることができます。

于 2013-09-21T14:01:20.907 に答える
2

この場合、最も簡単な方法は、前方宣言と、一部のコードをヘッダー ファイルからソース ファイルに移動することです。

このような

Player.h

#include "Bot.h"

class Game; // forward declaration

class Player {
    private:
    bool collision(Game g);
};

Player.cpp

#include "Player.h"
#include "Game.h"

bool Player::collision(Game g)  {

   for (Bot bot: g.bots)
   ...
}

Game前方宣言は、それがクラスの名前であることをコンパイラに伝えますが、それ以外のことは何もありません。したがって、このPlayer::collisionメソッドは、Game の完全な定義が利用可能な Player.cpp ファイルに移動する必要があります。

于 2013-09-21T13:40:42.307 に答える
1

AにBが含まれ、BにAが含まれている場合、無限のサイズになるため、これを実行できるとは思いません。実際には、前方宣言を使用して、相互へのポインターを格納する 2 つのクラスを作成して、2 つのクラスが互いの存在を認識できるようにすることができます。

于 2013-09-21T13:28:40.343 に答える
1

前方宣言が必要です - http://en.wikipedia.org/wiki/Forward_declaration

于 2013-09-21T13:29:27.160 に答える