Динамическая реализация в C ++ - PullRequest
2 голосов
/ 29 июля 2010

Я хочу, чтобы мой код был расширяемым, чтобы во время выполнения я создавал объекты.

Например, допустим, у меня есть класс Grocery, у которого есть массив фруктов, и я хочу заполнить этот массив фруктов объектами, которые получены из фруктов.

class Fruit{

};

class Grocery{

    std::vector<Fruit*> m_fruits;
};

class Apple: Fruit{

};

class Pineapple: Fruit{

};

Теперь во время выполнения я хочу, чтобы мой вектор класса Grocery m_fruits был заполнен объектами класса Apple и Pineapple. Так возможно ли это в некотором роде.

если я добавлю еще один фрукт в качестве клубники в будущем, его объект будет создан и динамически добавлен в вектор Grocery без изменения реализации класса Grocery?

Помощь по коду будет оценена.

Ответы [ 4 ]

4 голосов
/ 29 июля 2010

Проверьте свой учебник.Вероятно, упоминается, что вы можете полиморфно относиться только к указателям на типы.Другими словами, вектор указателей на фрукты может принимать указателей на яблоки или ананасы.

2 голосов
/ 29 июля 2010

Ну, если вы хотите сделать так, чтобы ваш класс Бакалеи мог генерировать любой тип фруктов. Даже фрукты, которые были реализованы после того, как продуктовый класс был заблокирован, я полагаю, вы могли бы получить что-то вроде следующего?

typedef Fruit*(*FruitInstantiatorPtr)();

template<class T>
Fruit* FruitInstantiator()
{
   return new T();
}


// Then in Grocery have a function like:

static void AddFruitGenerator(FruitInstantiatorPtr instantiatorFunc, string fruitTypeName);

////
//Then someone somewhere can go:

class MyNewFruit:Fruit{};

MyGrocery.AddFruitGenerator(FruitInstantiator<MyNewFruit>, "myAwesomeNewFruit");

И таким образом ваш класс Grocery сможет создать экземпляр любого типа фруктов, добавленных в будущем.

0 голосов
/ 29 июля 2010

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

Вам необходимо выполнить одно из следующих действий:

  1. Использованиевектор необработанных указателей на базовый тип, например std::vector<Fruit*>, и управляйте временем жизни отдельных Fruit экземпляров самостоятельно (это наименее желательный вариант).
  2. Используйте вектор интеллектуальных указателей на базувведите, например, std::vector<boost::shared_ptr<Fruit> >, и разрешите подсчет ссылок для управления временем жизни отдельных элементов.
  3. Используйте boost::ptr_vector<Fruit> для хранения элементов, и время жизни элементов привязано к времени жизни содержащего ptr_vector.

В зависимости от ваших потребностей предпочтительны № 2 и № 3.Следует избегать # 1, так как это требует ручных усилий для управления временем жизни и может легко привести к утечкам памяти, если выполнено неправильно.

0 голосов
/ 29 июля 2010

Предполагая, что Fruit имеет чисто виртуальные функции (обозначенные virtual func() = 0), вам нужно хранить указатели на объекты Fruit внутри вашего вектора std::vector<Fruit*>.

К сожалению, стандартные контейнеры не особенно хороши вобрабатывая указатели, и вам придется удалить все объекты внутри вашего вектора в деструкторе вашего Grocery.Вы могли бы рассмотреть shared_ptr из TR1 или библиотеки повышения.

Слово об именовании: Instantiation не является подходящим словом в этом случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...