Как динамически создавать объекты класса? - PullRequest
15 голосов
/ 24 октября 2010

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

Ответы [ 4 ]

19 голосов
/ 24 октября 2010

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

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

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

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

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

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

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

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

И то же самое для кошки.

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

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

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

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

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

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

Удачи.

5 голосов
/ 24 октября 2010

Следующий фабричный метод создает 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. Ознакомьтесь с шаблонами создания в шаблонах проектирования C ++ в викибуке , поскольку один из них, вероятно, относится к вашей проблеме.

3 голосов
/ 24 октября 2010

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

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;
}

Похожие: объектно-ориентированный шаблон проектирования "Фабрика"

0 голосов
/ 22 февраля 2018

Простой способ - использовать вектор.сначала включите векторную библиотеку и создайте временный объект в качестве вашего класса.

class temp;

затем создайте вектор для именованных объектов с типом вашего класса:

#include <vector>
.
.
vector <class>objects;

, затем вы можете добавитьцикл для добавления объекта. Например, у меня есть класс с именем temp, в котором есть функция с именем input, и я хочу добавить:

while(1){
        temp.input();
        objects.push_back(temp);
        }

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

objects[i];

, и если вы хотите удалить объект, просто используйте этот способ: 1. Определите местоположение вашего объекта в векторе.2. измените количество последнего блока вашего вектора на это и удалите последний блок:

objects[location of the object you want to remove]=objects[location of your last block];
objects.pop_back();

, если вы хотите узнать местоположение последнего блока вашего вектора, сделайте это:

int lastblock;
lastblock=(objects.size()-1);

примечание: вы можете использовать векторы как массив.

...