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 的析构函数中创建一个爆炸实例,并将其放在列表中。这样我就可以让它在 main 内部渲染和更新

4

3 回答 3

3

你的意思是Game_object应该持有一个std::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

也许访问这些列表不是一个好主意,但是如果您需要这种访问权限,您可以通过多种方式来实现,最简单的是全局变量:

// 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、方法GettersDeleters方法。要更新列表的内容,您可以将管理器的引用传递给渲染器/更新器,并从管理器获取对列表的引用:

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 回答
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) 时出现多个声明。然后只需要一个声明,在这种情况下,在源文件 (mylists.cpp) 中。

为了能够使用列表,只需包含头文件。

此外,在 mylists.h 中,还需要对类进行前向声明

class Game_object;
class Explosion;

这是为了避免未声明的标识符错误。

于 2012-10-11T07:55:20.593 回答