2010-01-15 77 views
3

我正在寻找一种方法来确定在运行时应分配哪种类型的对象(基于给定的类名称,其类型为const char*)。如何获得给定类名称的未知类的对象

嘛,当然最简单的方法是使用if S/else if小号加载,但似乎不适用,因为我有> 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变量或函数,可以解决这个问题,但会添加一些工作(当然,您可以使用宏来实现此目的,但是如果您已经使用宏,则可以使用另一个对象工厂方法)

+0

闻起来就像你需要实现一个工厂和'clone'方法。使用'clone()'接口,你可以创建一个家族的对象,而不需要知道他们的类名。 – 2010-01-16 01:04:17

+0

我不想看起来很重要,但真的......这味道不好。首先,'typeid'的使用是颇有争议的,但我也想指出这种方法的低效性>你执行一个线性复杂的搜索,并且你必须精确地确定所有可能生成的类型。 ..我甚至不想考虑噩梦般的维护成本。 – 2010-01-16 16:47:30

+0

typeid可以很容易地用static :: name函数代替,线性搜索不是一个问题,因为我只调用这个方法一次(除此之外,任何其他对象工厂ive看过也有一个线性搜索或滥用宏) – smerlin 2010-01-16 19:03:47

回答

3

你就不能申报

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

然后你就可以专门为

typename TBase, typename TDerived, typename TArg 
+0

wouldnt它甚至如果我这么做了,那么先递交一个递归步骤? – smerlin 2010-01-15 22:36:26

+0

你正试图获得1 +模板参数,而不是0+对吗?您可以专门针对0个案例的模板。一旦我了解你, – 2010-01-15 22:40:02

+0

就像一个魅力。 – smerlin 2010-01-15 23:30:32

2

的情况下阅读的答案在here,你可能需要一个工厂。

0

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

+0

使用该模式时,您必须自己编写代码,使用我的方式编译器为我生成;) – smerlin 2010-01-15 23:33:03

+0

@smerlin如果我理解*您的*方式,您需要在每次需要调用时链/写所有派生类'get_classobject()'。所以当添加一个类或删除一个时,这是一个管理/手动过程。我描述的方式是多一点*自动*。基本上你只需要添加两行。类声明中的METADECL和编译单元(.cpp文件)中的METAIMPL,最好靠近构造函数。这个解决方案的自动化功能是真正吸引我的,然后通过加载共享对象(.so/.dll文件)甚至可以在运行时添加类。完成了... – epatel 2010-01-16 00:25:50

+0

无论如何我只需要调用这个函数,并且如果我不得不多次调用它们,我会添加一个(内联)包装函数,这样我只需要编写一次类 – smerlin 2010-01-16 07:58:57

1

如何制作一个没有可变参数的专门化get_classobject()?这将停止递归。

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

+0

已经尝试过了,仍然有 错误:没有匹配函数调用get_classobject( const char *&)'|' – smerlin 2010-01-15 23:07:59