如何使用给定的类名获取未知类的对象

时间:2010-01-15 22:14:00

标签: c++ c++11 function-templates

我正在寻找一种在运行时确定应该分配哪种类型对象的方法(基于给定的类名,类型为const char*)。

当然,最简单的方法是使用if s / else if s的负载,但这似乎不适用,因为我有> 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变量或函数,可以解决这个问题,但会增加一些工作(当然你可以使用宏来做这个,但如果你已经使用了宏,你也可以使用另一个对象工厂方法)

4 个答案:

答案 0 :(得分:3)

你能不能宣布

template<typename TBase, typename TDerived, typename TArg, typename... TArgs>

然后你可以专注于

的情况
typename TBase, typename TDerived, typename TArg

答案 1 :(得分:2)

阅读here上的答案,您可能需要一家工厂。

答案 2 :(得分:1)

如何制作一个没有可变参数temlates的专用get_classobject()?那会阻止递归。

然后,您将拥有一个带有可变参数模板的定义,另一个只有template<typename TBase, typename TDerived>。另一个想法是创建一个非模板重载,它只接受const char *,并返回0。

答案 3 :(得分:0)

这听起来像是在寻找经典的对象工厂模式。看看这个stackoverflow question。我个人喜欢这个method