2

初期化したクラスのグループがアクセスして使用できるグローバル リストを作成する必要がありますが、それらのクラスを含めてリストを作成する必要があります。何か案は?

例:

class Game_object
{
  public:
  ~Game_object()
  void Update();
  void Render();
  //Other stuff
};

class Explosion
{
    Stuff
};

class Player
{
      Stuff
};

これらのクラスはすべて、別のヘッダー ファイルにある以下のリストと、私の int main にアクセスする必要があります。

std::list <Game_object *> Objects;
std::list <Explosion *> Explosions;

等々。

アイデアは、Game_object のデストラクタで爆発インスタンスを作成し、それをリスト内に配置できるというものでした。これは、メイン内でレンダリングおよび更新できるようにするためでした

4

3 に答える 3

3

つまりGame_object、astd::list<Explosion *>Explosion保持し、std::list<Game_object *>?を保持する必要があります。前方宣言の仕事のように聞こえます:

#include <list>

class Game_object;
class Explosion;

class Game_object
{
    std::list<Explosion *> l;
};

class Explosion
{
    std::list<Game_object *> l;
};

これは、リストに実際のオブジェクトではなくポインタが含まれているために機能します。

于 2012-10-11T07:45:08.343 に答える
0

次のように、ヘッダーファイル(mylists.hなど)でリストを宣言します。

#include <list>
#include <myGameClasses.h>

class Game_object;
class Explosion;

extern std::list<Game_object*> Objects;
extern std::list<Explosion*> Explosions;
// And so for other lists

externを使用すると、リストの参照宣言が作成されます。次に、ソースファイル(mylists.cppなど)に定義宣言を作成する必要があります。

#include "mylists.h"

std::list<Game_object*> Objects;
std::list<Explosion*> Explosions;
// And so for other lists

どうしてこんな風にやらなきゃいけないの?これは、ヘッダー(mylists.h)を含めるときに複数の宣言を防ぐためです。その場合、必要な宣言は1つだけで、この場合はソースファイル(mylists.cpp)にあります。

リストを使用できるようにするには、ヘッダーファイルをインクルードするだけです。

また、mylists.hでは、クラスの前方宣言も必要です。

class Game_object;
class Explosion;

これは、宣言されていない識別子のエラーを回避するためです。

于 2012-10-11T07:55:20.593 に答える
0

これらのリストにアクセスするのは得策ではないかもしれませんが、この種のアクセスが必要な場合は、さまざまな方法でアクセスできます。グローバル変数による最も簡単な方法は次のとおりです。

// forward declare Game_object:
class Game_object;

// Declare lists:
typedef std::list <Game_object *> ListObjects;
typedef std::list <Explosion *> ListExplosions;
ListObjects Objects;
ListExplosions Explosions;

class Game_object
{
    public:
    void Update()
    {
        // Update Objects...
        for (ListObjects::const_iterator O = Objects.begin(); O != Objects.end(); ++O)
        { ... };
        // Update Explosions...
        for (ListExplosions::const_iterator E = Explosions.begin(); E != Explosions.end(); ++E)
        { ... };
    };
    void Render()
    {
        // Render Objects...
        for (ListObjects::const_iterator O = Objects.begin(); O != Objects.end(); ++O)
        { ... };
        // Render Explosions...
        for (ListExplosions::const_iterator E = Explosions.begin(); E != Explosions.end(); ++E)
        { ... };
    };
    //Other stuff
};

それは良い考えではありません.グローバル変数は面倒であり、他のクラスがアクセスしてその内容を変更する可能性のあるグローバルリストでは、別のクラスが同時に内容を変更しようとするとさらに悪化する可能性があります. ただし、スレッドを使用していない場合は、それほど面倒ではありません。

他のアプローチは、マネージャーを作成することです。管理者はリストの所有者である必要があり、メソッド、、およびメソッドがSetters必要GettersですDeleters。リストの内容を更新するには、マネージャーへの参照をレンダラー/アップデーターに渡し、マネージャーからリストへの参照を取得します。

class ObjectManager
{
public:
    typedef std::list <Game_object *> ListObjects;

    void AddObject(const ObjectStuff &os)
    { ... };

    const ListObjects &GetObjects()
    { return Objects; };

private:
    ListObjects Objects;
}

class ExplosionManager
{
public:
    typedef std::list <Explosion *> ListExplosions;

    void AddExplosion(const ExplosionStuff &es);
    { ... };

    const ListExplosions &GetExplosions()
    { return Explosions; };

private:
    ListExplosions Explosions;
}

void Render(const ObjectManager &om)
{
    // Ask ObjectManager for the object list
}

void Render(const ExplosionManager &em)
{
    // Ask ExplosionManager the explosion list
}

上記のコードは単純で非常に単純な概算ですが、例としてのみ使用しています。上記のアプローチの利点は、リストが所有者オブジェクトによってのみ変更されることです。リストがマネージャーから必要な場合は読み取り専用の方法で提供され、スレッドを使用している場合は、ロックを追加するのが非常に簡単です。リストの使用中の変更を避けるために、マネージャ メソッドでロックを解除します。


これは尋ねられませんが、言う価値があると思います: オブジェクト ポインターをコンテナーに格納することを避け、オブジェクト インスタンスごとにストア タイプを変更することをお勧めします。

std::list <Game_object *> VS std::list <Game_object>

ポインターを使用している場合は、オブジェクトの割り当てと割り当て解除を処理する必要があります。リストがグローバルCloseである場合、リストが所有されている場合、リストに格納されているポインターによって管理されるすべてのメモリの割り当てを解除するパブリック メソッドが必要です。オブジェクトによって、同じプロセスをオブジェクト デストラクタに実行する必要があります。

ただし、オブジェクト インスタンスを格納している場合、リスト デストラクタは、有効期間が終了したときに格納されているすべてのオブジェクトの割り当てを解除します。コードはよりクリーンで維持しやすくなります。

于 2012-10-11T08:28:35.140 に答える