2013-10-06 128 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; }); 

这样的解析器可以创造一切派生类型。