Существует ли способ инстанцировать объектов от строки, содержащей их имя класса?

Я полагаю, у вас есть строка, подобная этой

let string = """
    "Who composed the
    popular song "Aati Kya
    Khandala" from 'Ghulam"?
    Jatin- Lalit
    Abhijeet
    Aamir Khan"
"""

или подобная

let string = """
    "Who composed the\npopular song "Aati Kya\nKhandala" from 'Ghulam"?\nJatin- Lalit\nAbhijeet\nAamir Khan"
"""

Итак, сначала разделите вашу строку на массив строк

var separated = string.components(separatedBy: "\n")
[1110 ] затем вставьте новую строку в индекс, где вам нужно

separated.insert("sagarduhanishere", at: separated.endIndex - 3)

, а затем просто присоедините этот массив обратно к одной строке

let joined = separated.joined(separator: "\n")

var separated = string.components(separatedBy: "\n")
separated.insert("sagarduhanishere", at: separated.endIndex - 3)
let joined = separated.joined(separator: "\n")
print(joined)

[116 ]

135
задан Lightness Races with Monica 26 July 2011 в 14:09
поделиться

6 ответов

Нет, нет ни одного, если Вы не делаете отображение себя. C++ не имеет никакого механизма для создания объектов, типы которых определяются во времени выполнения. Можно использовать карту, чтобы сделать то отображение себя, хотя:

template<typename T> Base * createInstance() { return new T; }

typedef std::map<std::string, Base*(*)()> map_type;

map_type map;
map["DerivedA"] = &createInstance<DerivedA>;
map["DerivedB"] = &createInstance<DerivedB>;

И затем можно сделать

return map[some_string]();

Получение нового экземпляра. Другая идея состоит в том, чтобы иметь регистр типов themself:

// in base.hpp:
template<typename T> Base * createT() { return new T; }

struct BaseFactory {
    typedef std::map<std::string, Base*(*)()> map_type;

    static Base * createInstance(std::string const& s) {
        map_type::iterator it = getMap()->find(s);
        if(it == getMap()->end())
            return 0;
        return it->second();
    }

protected:
    static map_type * getMap() {
        // never delete'ed. (exist until program termination)
        // because we can't guarantee correct destruction order 
        if(!map) { map = new map_type; } 
        return map; 
    }

private:
    static map_type * map;
};

template<typename T>
struct DerivedRegister : BaseFactory { 
    DerivedRegister(std::string const& s) { 
        getMap()->insert(std::make_pair(s, &createT<T>));
    }
};

// in derivedb.hpp
class DerivedB {
    ...;
private:
    static DerivedRegister<DerivedB> reg;
};

// in derivedb.cpp:
DerivedRegister<DerivedB> DerivedB::reg("DerivedB");

Вы могли решить создать макрос для регистрации

#define REGISTER_DEC_TYPE(NAME) \
    static DerivedRegister<NAME> reg

#define REGISTER_DEF_TYPE(NAME) \
    DerivedRegister<NAME> NAME::reg(#NAME)

, я уверен, что существуют лучшие названия тех двух все же. Другая вещь, которая, вероятно, имеет смысл использовать здесь, shared_ptr.

, Если у Вас есть ряд несвязанных типов, которые не имеют никакого общего базового класса, можно дать указателю функции тип возврата boost::variant<A, B, C, D, ...> вместо этого. Как то, если у Вас есть класс Нечто, Панель и Baz, это похоже на это:

typedef boost::variant<Foo, Bar, Baz> variant_type;
template<typename T> variant_type createInstance() { 
    return variant_type(T()); 
}

typedef std::map<std::string, variant_type (*)()> map_type;

А boost::variant похож на объединение. Это знает, какой тип хранится в нем путем взгляда, какой объект использовался для инициализации или присвоения ей. Взгляните на его документацию здесь . Наконец, использование необработанного указателя функции является также немного староватым. Современный код C++ должен быть разъединен от определенных функций / типы. Можно хотеть изучить Boost.Function для поиска лучшего пути. Это было бы похоже на это тогда (карта):

typedef std::map<std::string, boost::function<variant_type()> > map_type;

std::function будет доступно в следующей версии C++ также, включая [1 111].

219
ответ дан 23 November 2019 в 23:46
поделиться

Нет нет. Мое предпочтительное решение этой проблемы состоит в том, чтобы создать словарь, который отображает имя к методу создания. Классы, которые хотят быть созданными как это тогда, регистрируют метод создания в словаре. Это обсуждено в некоторых деталях в книга .

шаблонов GoF
7
ответ дан 23 November 2019 в 23:46
поделиться

Короткий ответ - Вы, не может. Посмотрите их ТАК вопросы для почему:

  1. , Почему C++ не имеет отражения?
  2. , Как я могу добавить отражение к приложению C++?
6
ответ дан 23 November 2019 в 23:46
поделиться

Я ответил в другом ТАК на вопрос о фабриках C++. См. там , если гибкая фабрика представляет интерес. Я пытаюсь описать старый путь с ET ++ для использования макросов, которые работали отлично для меня.

ET ++ было проектом портировать старого MacApp на C++ и X11. В усилии его Eric Gamma и т.д. начал думать приблизительно Шаблоны разработки

4
ответ дан 23 November 2019 в 23:46
поделиться

Значение отражения как в Java. здесь существует некоторая информация: http://msdn.microsoft.com/en-us/library/y0114hz2 (По сравнению с 80) .aspx

Вообще говоря, ищите Google "отражение C++"

1
ответ дан 23 November 2019 в 23:46
поделиться

Это - шаблон "фабрика". Посмотрите Википедию (и этот пример). Вы не можете создать тип по сути из строки без некоторого вопиющего взлома. Почему Вам нужно это?

0
ответ дан 23 November 2019 в 23:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: