Je cherche un moyen de déterminer à l'exécution, quel type d'objet doit être alloué (basé sur un nom de classe donné, qui est de type const char*
). Eh bien la façon la plus simple est bien sûr d'utiliser des charges de if
s/else if
s, mais cela ne semble pas applicable, parce que j'ai plus de 100 classes différentes (enfin, elles dérivent toutes d'une classe de base), et j'ai ajouter régulièrement de nouvelles classes.Comment obtenir un objet d'une classe inconnue avec le nom de classe donné
Je suis déjà venu avec un premier projet, mais malheureusement, il ne marche pas compilez encore (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;
}
mais que gcc d'arrêt sizeof...(TArgs)>0
ne marche pas essayer de générer du code pour get_classobject<TBase,const char*>(const char*)
qui ne
Avez-vous une idée, comment résoudre ce problème ou une autre idée? Merci.
EDIT: Je l'ai résolu:
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);
}
EDIT Pour les lecteurs intéressés:
Vous devriez maintenant que la mise en œuvre est compilateur ne indépendant au-dessus du tout. La sortie de typeif(sometype).name()
est spécifique au compilateur/implémentation. L'utilisation d'une variable ou d'une fonction static const char* name
dans toutes les classes dérivées corrige cela, mais ajoute beaucoup de travail (bien sûr, vous pouvez utiliser une macro, mais si vous utilisez déjà des macros, vous pouvez également utiliser une autre méthode d'objet)
Vous avez besoin d'implémenter une méthode factory et 'clone'. En utilisant une interface 'clone()', vous pouvez créer des objets d'une famille et ne pas avoir besoin de connaître le nom de leur classe. –
Je ne veux pas paraître critique, mais vraiment ... ça sent mauvais. Tout d'abord l'utilisation de 'typeid' est assez controversée, mais je voudrais aussi souligner l'inefficacité d'une telle méthode> vous effectuez une recherche avec une complexité linéaire et vous devez réellement préciser TOUS les types possibles qui pourraient être générés. .. et je ne veux même pas penser au coût d'entretien cauchemardesque. –
typeid peut être facilement substitué avec une fonction static :: name, la recherche linéaire n'est pas une issure puisque je n'appelle cette méthode qu'une seule fois (à part que toute autre usine d'objet a aussi une recherche linéaire ou abuse des macros) – smerlin