Подтвердить что ты не робот

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

Скажем, у меня есть поле класса, и пользователь может создавать поля. Как это сделать? Я понимаю, что я создаю объекты className objectName(args);, но как это сделать динамически, в зависимости от ввода пользователя?

4b9b3361

Ответ 1

Правильный ответ зависит от количества различных классов, из которых вы хотите создать экземпляры.

Если число огромно (приложение должно иметь возможность создать экземпляр любого класса в вашем приложении), вы должны использовать функциональные возможности отражения .Net. Но, честно говоря, я не большой поклонник использования рефлексии в бизнес-логике, поэтому я бы посоветовал не делать этого.

Я думаю, что на самом деле у вас ограниченное число на классах, для которых вы хотите создавать экземпляры. И все остальные ответы делают это предположение. Вам действительно нужен шаблон factory. В следующем коде я также предполагаю, что классы, которые вы хотите создать экземпляры, все происходят из одного и того же базового класса, скажем, Animal, например:

class Animal {...};
class Dog : public Animal {...}
class Cat : public Animal {...}

Затем создайте абстрактный factory, который представляет собой интерфейс, который создает животное:

class IFactory
   {
   public:
      Animal *create() = 0;
   };

Затем создайте подклассы для каждого из разных видов животных. Например. для класса Dog это станет следующим:

class DogFactory : public IFactory
   {
   public:
      Dog *create() {return new Dog();}
   };

И то же самое для cat.

Метод DogFactory:: create перекрывает метод IFactory:: create, даже если их тип возврата отличается. Это то, что называется совместными вариантами возврата. Это разрешено до тех пор, пока возвращаемый тип метода подкласса является подклассом возвращаемого типа базового класса.

Теперь вы можете поместить экземпляры всех этих фабрик на карту, например:

typedef std::map<char *,IFactory *> AnimalFactories
AnimalFactories animalFactories;
animalFactories["Dog"] = new DogFactory();
animalFactories["Cat"] = new CatFactory();

После ввода пользователя вы должны найти правильный factory и попросить его создать экземпляр животного:

AnimalFactories::const_iterator it=animalFactories.find(userinput);
if (it!=animalFactories.end())
   {
   IFactory *factory = *it;
   Animal *animal = factory->create();
   ...
   }

Это типичный абстрактный подход factory. Есть и другие подходы. Когда я преподавал С++, я написал небольшую статью CodeProject об этом. Вы можете найти его здесь: http://www.codeproject.com/KB/architecture/all_kinds_of_factories.aspx.

Удачи.

Ответ 2

Следующий factory метод создает экземпляры Box динамически на основе пользовательского ввода:

class BoxFactory
{
  public:
    static Box *newBox(const std::string &description)
    {
      if (description == "pretty big box")
        return new PrettyBigBox;
      if (description == "small box")
        return new SmallBox;
      return 0;
    }
};

Конечно, PrettyBigBox и SmallBox оба выводятся из Box. Посмотрите на шаблоны создания в шаблоны проектирования С++ wikibook, поскольку один из них, вероятно, относится к вашей проблеме.

Ответ 3

В С++ можно выделять объекты с помощью автоматического (стека) и динамического (кучного) хранилища.

Type variable_name; // variable_name has "automatic" storage.
                    // it is a local variable and is created on the stack.

Type* pointer_name = NULL; // pointer_name is a "pointer". The pointer, itself,
                           // is a local variable just like variable_name
                           // and is also created on the stack. Currently it
                           // points to NULL.

pointer_name = new DerivedType; // (where DerivedType inherits from Type). Now
                                // pointer_name points to an object with
                                // "dynamic" storage that exists on the heap.

delete pointer_name; // The object pointed-to is deallocated.
pointer_name = NULL; // Resetting to NULL prevents dangling-pointer errors.

Вы можете использовать указатели и распределение кучи для динамического построения объектов, как в:

#include <cstdlib>
#include <iostream>
#include <memory>
class Base {
    public:
        virtual ~Base(){}
        virtual void printMe() const = 0;
    protected:
        Base(){}
};
class Alpha : public Base {
     public:
        Alpha() {}
        virtual ~Alpha() {}
        virtual void printMe() const { std::cout << "Alpha" << std::endl; }
};
class Bravo : public Base {
     public:
        Bravo() {}
        virtual ~Bravo() {}
        virtual void printMe() const { std::cout << "Bravo" << std::endl; }
};
int main(int argc, char* argv[]) {
    std::auto_ptr<Base> pointer; // it is generally better to use boost::unique_ptr,
                                 // but I'll use this in case you aren't familiar
                                 // with Boost so you can get up and running.
    std::string which;
    std::cout << "Alpha or bravo?" << std::endl;
    std::cin >> which;
    if (which == "alpha") {
        pointer.reset(new Alpha);
    } else if (which == "bravo") {
        pointer.reset(new Bravo);
    } else {
        std::cerr << "Must specify \"alpha\" or \"bravo\"" << std::endl;
        std::exit(1);
    }
    pointer->printMe();
    return 0;
}

Связано: объектно-ориентированный шаблон дизайна Factory