【发布时间】:2010-01-15 22:13:59
【问题描述】:
我正在寻找一种方法来确定在运行时应分配哪种类型的对象(基于给定的类名,其类型为 const char*)。
当然,最简单的方法是使用 ifs /else ifs 的负载,但这似乎不适用,因为我有超过 100 个不同的类(至少它们都派生自一个基类),而且我还必须定期添加新课程。
我已经提出了初稿,但遗憾的是它还没有编译(mingw & g++ 4.4)
template<typename TBase, typename TDerived, typename... TArgs>
Base* get_classobject(const char* classname)
{
if(strcmp(classname,typeid(TDerived).name())==0)
return new TDerived; //
else if(sizeof...(TArgs)>0)
return get_classobject<TBase,TArgs...>(classname);
else
return 0;
}
int main()
{
Base* obj = get_classobject<Base,A,Foo,B,C>("Foo");
// ^- Types A B C and Foo are all derived from Base
delete obj; //of course we got an virtual dtor ;)
return 0;
}
但是 sizeof...(TArgs)>0 并不能阻止 gcc 尝试为失败的 get_classobject<TBase,const char*>(const char*) 生成代码
你有什么想法,如何解决这个问题,或任何其他想法? 谢谢。
编辑:我解决了:
template<typename TBase, typename TDerived>
Base* get_classobject(const char* classname)
{
if(strcmp(classname,typeid(TDerived).name())==0)
return new TDerived;
return 0;
}
template<typename TBase, typename TDerived, typename TArg, typename... TArgs>
Base* get_classobject(const char* classname)
{
if(strcmp(classname,typeid(TDerived).name())==0)
return new TDerived;
return get_classobject<TBase,TArg,TArgs...>(classname);
}
编辑感兴趣的读者:
您现在应该知道上面的实现根本不是独立于编译器的。
typeif(sometype).name() 的输出是特定于编译器/实现的。
在所有派生类中使用static const char* name 变量或函数可以解决此问题,但会增加大量工作(当然您可以为此使用宏,但如果您已经在使用宏,您也可以使用另一个对象工厂方法)
【问题讨论】:
-
闻起来像你需要实现一个工厂和
clone方法。使用clone()接口,你可以创建一个家族的对象,而不需要知道它们的类名。 -
我不想显得挑剔,但真的......这闻起来很糟糕。首先,
typeid的使用颇具争议,但我还想指出这种方法的效率低下 > 您执行具有线性复杂性的搜索,并且您必须实际精确所有可能生成的类型。 ..我什至不想考虑噩梦般的维护成本。 -
typeid 可以很容易地用静态 ::name 函数替换,线性搜索不是问题,因为我只调用过一次此方法(除了我查看的任何其他对象工厂也有线性搜索或滥用宏)
标签: c++ c++11 function-templates