2013-10-06 182 views
0

背景:創建類的實例

在我的遊戲引擎,我有一個用來通過解析一個腳本文件來創建遊戲實體通用的「腳本解析器」。所以在代碼中你可能會有類似的東西MyEntity* entity = MyScriptParer::Parse("filename.scr");

任何要編寫腳本的類都從一個通用基類繼承。在內部,在遊戲引擎有使用這個有些特殊的類 - 顆粒,字體等,這都很好地工作在解析器 - 見下文

std::string line; 
std::getline(ifs, line); 

if (line == "[FONT]") { 
    CFont* f = new CFont(); 
    f->readObject(ifs); 
} 
else if (line == "[PARTICLE]") { 
    CParticle* p = new CParticle(); 
    p->readObject(ifs); 
} 
... 

提取我的問題帶有如何處理用戶定義的類在IE班使用遊戲引擎的遊戲。基類有一個抽象方法readObject,所以繼承的任何東西都必須實現這個方法。

問題是解析器如何知道新類?例如說我有一個CVehicle類解析器現在需要知道的認識「[車輛]」,也可以創建一個new CVehicle

有什麼辦法來存儲陣列/圖類類型或東西,以便也許我可以有一個函數來註冊一個帶有字符串的類類型列表來提供一個查找來創建新的實例?

一個長鏡頭的

位,因此如果任何人有關於如何處理,他們將受到歡迎

回答

1

可以店通過std::type_info

然而,在一個陣列/圖類類型,你不能從這個創建一個類型,因爲它需要更多的RTTI比C適用++。 (如.NET中的反射)。

但是,您可以在這樣的地圖中存儲函數指針到類工廠。 也就是說

typedef CBaseClass* (*pfnCreateClass)(); 

std::map<std::string, pfnCreateClass> mapCreate; 

// Registering 
// CMyCustomClass::GetClass() is a static method that creates a CMyCustomClass 
mapCreate.insert(std::pair<std::string, pfnCreateClass>("[CUSTOM_CLASS]", CMyCustomClass::GetClass)); 

// Get class 
std::map<std::string, pfnCreateClass>::const_iterator it = mapCreate.find(line); 
if(mapCreate.end() != it) 
{ 
    CBaseClass *p = it->second(); 
    p->readObject(ifs); 
} 
+0

嗨,感謝您提供的信息豐富的答案。我會試試看看它是如何發展的。 – Zammalad

+0

好的,我喜歡這種方法,因爲這意味着我可以讓整個腳本閱讀器更通用一些,甚至在添加新遊戲引擎時添加內部腳本。儘管我試圖實現並遇到一個問題。它是與'CMyCustomClass :: GetClass()'部分。如果我嘗試按照您的示例傳遞它,編譯器會失敗,並且不能使用「CFont *()」類型的左值初始化類型爲'CBaseClass *(*)()'的參數:不同的返回類型('CBaseClass *' vs'CFont *')「 – Zammalad

+1

我解決了我的問題。在這種情況下,我傳遞一個指向新客戶類「CFont」的指針的簡單錯誤,而不是將它傳回基類指針 – Zammalad

0

解析其他建議只是要註冊一個新的類型採取的類型名稱的功能是不可能的和一個創建類型的函數。

事情是這樣:

void RegisterType(std::string name, std::function< BaseType() > createFunc); 

當註冊一個新的類型,你做它像這樣:

RegisterType("Vehicle", [](){ return new CVehicle; }); 

這樣的解析器可以創造一切派生類型。