Как получить объект неизвестного класса с заданным именем класса

StackOverflow https://stackoverflow.com/questions/2075123

  •  20-09-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

Не могли бы вы просто заявить

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

?

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

typename TBase, typename TDerived, typename TArg

Другие советы

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top