2012-10-11 24 views
2

我需要创建一个全局列表,该列表可以被我已经初始化的一组类所访问和使用,但是需要包含这些类来创建名单。有任何想法吗?创建一个必须被它使用的类访问的列表C++

例子:

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

class Explosion 
{ 
    Stuff 
}; 

class Player 
{ 
     Stuff 
}; 

所有这些类需要以下访问列表,这是另一个头文件,以及我INT主要

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

等。

这个想法是我可以在Game_object的析构函数中创建一个爆炸实例,并将它放在列表中。这是我可以让它渲染和更新主

+1

根据我的经验,对这个问题的更好的解决方案是让这些类*不需要通过移动其他地方需要的逻辑来访问这些列表。 – molbdnilo

+0

我必须同意molbdnilo在这里,搞乱前面的声明和extern会导致难以维护,相互依赖的意大利面代码。最好的方法是重新设计你在做什么。 –

回答

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; 
}; 

这工作,因为你的列表中包含指针,而不是实际的对象。

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; 

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

+0

这就是我试图去做的方式,但是为了包含Game_object,我需要包含Game_object头文件,它会给我一个错误,指出game_object和爆炸类不存在 – Masoman3

+0

@ Masoman3您确定添加了吗?你的课程的前瞻性声明? –

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 
}; 

这不是一个好主意,全局变量可能会很麻烦,甚至更糟糕的是全局列表可以被其他类访问并且改变它的内容,而另一个类尝试同时修改内容;但如果你不使用线程,它不会那么麻烦。

其他方法可能是创建一个经理。经理必须是该列表的所有者,并且需要方法SettersGettersDeleters方法。要更新列表中的内容可以传递给管理者参考,以渲染/更新,并获得从管理列表的引用:

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方法来解除分配列表中存储的指针所管理的所有内存,如果列表属于一些对象,你需要在对象析构函数中执行相同的过程。

但是,如果您要存储对象实例,那么列表析构函数将释放所有存储的对象,这些对象在其生命周期结束时会取消分配,代码更清晰且更易于维护。

相关问题