2013-12-04 4 views
0

Я хочу создать объект класса с именем строки, уже известной мной i.e динамически.Создайте объект класса с именем предопределенной строки

Предположим, у меня есть класс A и string str="ab" , так что я должен создать объект A ab; , но я не могу определить «AB», как это должно быть, как A str, так как str может динамически изменяться.

+2

Невозможно в C++ - нет никакого отражения в отличие от java – Constantin

+2

Каким будет случай использования? –

+0

Возможно, вы пытаетесь сериализовать объект в строку. – Extrakun

ответ

4

Вы можете использовать структуру данных карты, при этом ключ является именем класса, а значение является фабричным классом для создания объекта или указателем на функцию, которая при запуске вернет объект. Однако вам может потребоваться отбросить построенный объект до нужного вам типа.

Пример (Извинения для моей ржавой C++ кода):

Во-первых, у нас есть интерфейс для фабрики класса

class IObjectFactory 
{ 
    public: 
    virtual ~IObjectFactory() {} 
    virtual void* Create() = 0; 

}; 

Затем конкретную реализацию. Я просто сделаю встроенный.

class ConcreteObjectFactory : public IObjectFactory 
{ 
    public: 
    void* Create() { return new ConcreteObject(); } 
}; 

Теперь о карте.

using namespace std; 
map<string, shared_ptr<IObjectFactory> > classMap; 

// register the type 
classMap["concreteObject"].reset(new ConcreteObjectFactory()); 

// using it, albeit you take all kinds of risks if the string is not found 
// or points to the wrong type. 

ConcreteObject* o = 
    static_cast<ConcreteObject *>(classMap["concreteObject"]->Create()); 

Существует много способов улучшить этот ответ. Для тех, кого это интересует, я предлагаю проверить главу о RTTI в «Программе для программистов на C++»

+1

Я думаю, она хочет использовать переменную времени выполнения как идентификатор. –

+0

@BenjaminBannier: Я думаю, что он * думает *, он хочет. Но, по моему опыту, почти каждый раз, когда кто-то думает, что они хотят чего-то подобного, то, что они действительно хотят, это карта, они просто не знают, как правильно ее спросить (если бы они это сделали, они, вероятно, уже знали о картах , и не нужно будет задавать вопрос). - С учетом сказанного, я действительно думаю, что OP ищет просто 'map '. –

+0

@BenjaminLindley: Да, это имеет смысл. Возможно, Extrakun может добавить пример к его ответу, чтобы сделать более ясным, как это решение. –

0

Я не думаю, что это возможно. Если кто-нибудь даст вам ответ, вы можете обойти проблему таким образом :

class A { 
public: 
    A(const std::string& name) : name_(name) {} 
    inline std::string name() { return name_; } 
private: 
    std::string name_; 
} 

таким образом, у вас есть неявное преобразование из строки в а, так:

std::string className = "myName"; 
std::cout << (A)className->name(); /* print "myName" */ 

в противном случае вы могли бы использовать структуру данных карты, как предполагают Extrakun.

+0

Что это делает? –

1

Имя переменной не является частью программы, или, точнее, имя не существует в памяти. Это просто «ручка» или «знак», позволяющий программистам легко получить доступ к переменной, т.е. найдите, где содержимое переменной находится в памяти.

Другими словами, после того, как часть кода была скомпилирована в файл объекта, имена больше не существуют.

В вашем случае «ab» на самом деле является содержимым в памяти, когда «ab» появляется в памяти, ваша программа уже выполняется во время выполнения, в то время нет имен переменных вообще.

+0

Спасибо за ваши ans, но в моем случае я использовал объект ab и инициализировал его, и у меня так много объектов класса A, которые были уже определены и инициализированы, но я хочу, чтобы они снова получили доступ в соответствии с выбором пользователя, поэтому я хочу имя объекта, который будет задан динамически, есть ли способ сделать это? – user3065186

+0

Вы имеете в виду, что вы уже создали экземпляр пучка объектов, но хотите использовать один из них динамически, указав тег имени, чтобы указать, какой именно объект вам действительно нужен? Если это так, вы можете построить карту (например, std :: map objs;), ключи для карты могут быть такими именами, как «ab», а затем вы можете получить конкретный объект objs ["ab"] , –

0

В некоторых случаях возможно перейти от имени к переменной того имени, которое уже существует (т. Е. Не создавать его сейчас). Это работает с dlsym в UNIX или GetProcAddress на Windows. Символ должен быть виден, таким образом глобальный и в Windows явно экспортируется из библиотеки. Остерегайтесь проблем с именем «mangling».

Невозможно создать такой способ, кроме, конечно же, обходного пути генерации кода, если предполагается, что присутствует компилятор, создавая его в библиотеке.

В вашем случае вы, вероятно, захотите использовать карту из строки в переменные, и если вы хотите, чтобы одна и та же карта могла хранить разные типы значений, вы можете использовать boost::any как тип значения вашей карты.

Смежные вопросы