2012-10-11 27 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方法來解除分配列表中存儲的指針所管理的所有內存,如果列表屬於一些對象,你需要在對象析構函數中執行相同的過程。

但是,如果您要存儲對象實例,那麼列表析構函數將釋放所有存儲的對象,這些對象在其生命週期結束時會取消分配,代碼更清晰且更易於維護。

相關問題