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

我的问题在于如何处理用户定义的类,即使用游戏引擎的游戏中的类。基类有一个抽象方法readObject,所以任何继承的东西都必须实现这个方法。

问题是解析器如何知道新类?例如,假设我有一个CVehicle类,解析器现在需要知道以识别“[VEHICLE]”并且还能够创建一个new CVehicle

有没有办法在数组/映射中存储类类型或其他东西,所以也许我可以有一个函数来注册一个带有字符串的类类型列表,以提供创建新实例的查找?

有点长镜头,可能不可能,所以如果有人对如何处理解析有其他建议,他们将受到欢迎

4

2 回答 2

1

可以通过std::type_info将类类型存储在数组/映射中

但是,您不能由此创建类型,因为它需要的 RTTI 比 C++ 中可用的多。(如 .NET 中的反射)。

但是,您可以在这样的映射中存储指向类工厂的函数指针。IE

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);
}
于 2013-10-06T21:18:18.293 回答
0

只需要注册一个新类型的函数就可以接收类型的名称和一个用于创建类型的函数。

像这样:

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

注册新类型时,您可以这样做:

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

这样解析器就可以创建所有派生类型。

于 2013-10-06T21:14:25.630 回答