2010-10-24 6 views
12

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

+3

Можете ли вы привести пример (потенциально псевдокод)? –

+0

Создайте их где? Например, вы можете хранить их в 'std :: vector', но это действительно зависит от того, что вы делаете. – GManNickG

+0

К сожалению, в C++ вы не можете динамически вызвать конструктор. Единственный способ - хранить объекты, которые могут вернуть новый построенный объект того, что вы хотите во время выполнения. Примеры ответов, которые вы уже получили, полностью уместны. –

ответ

5

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

2

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

Связанный: the "Factory" object-oriented design pattern

15

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

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

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

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

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

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

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

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++, я написал небольшую статью CodeProject об этом. Вы можете найти его здесь: http://www.codeproject.com/KB/architecture/all_kinds_of_factories.aspx.

Удачи.

0

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

class temp; 

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

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

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

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

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

objects[i]; 

и если вы хотите, чтобы удалить объект, просто использовать этот способ: 1.find ваше местоположение объекта в векторе. 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); 

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

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