Как получить объект неизвестного класса с заданным именем класса - PullRequest
3 голосов
/ 16 января 2010

Я ищу способ определить во время выполнения, какой тип объекта должен быть выделен (на основе заданного имени класса типа const char*).

Ну, конечно, самый простой способ - это использовать нагрузки if с / 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 внутри всех производных классов исправит это, но добавит кучу работы (конечно, вы можете использовать макрос для этого, но если вы уже используете макросы, вы также можете использовать другой метод фабрики объектов )

Ответы [ 4 ]

3 голосов
/ 16 января 2010

Разве вы не можете просто объявить

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

Тогда вы можете специализироваться на случае

typename TBase, typename TDerived, typename TArg
2 голосов
/ 16 января 2010

Прочитайте ответы более здесь , вам, вероятно, нужна фабрика.

1 голос
/ 16 января 2010

Как насчет создания специализированного get_classobject () без вариабельных шаблонов? Это остановит рекурсию.

В таком случае у вас будет одно определение с шаблоном с переменными числами, а другое - просто template<typename TBase, typename TDerived>. Другая идея состоит в том, чтобы сделать перегрузку без шаблона, которая принимает просто const char * и возвращает 0.

0 голосов
/ 16 января 2010

Звучит так, будто вы ищете шаблон фабрики классических объектов. Посмотрите на этот stackoverflow вопрос . Лично мне нравится этот метод

...