2010-07-28 2 views
2

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

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

class Fruit{ 

}; 

class Grocery{ 

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

class Apple: Fruit{ 

}; 

class Pineapple: Fruit{ 

}; 

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

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

Код help будет оценен.

+1

Это домашнее задание? –

+18

используйте указатели, или вы получите нарезанные фрукты ... (google «C++ slicing») – smerlin

+1

@smerlin: могу ли я уменьшить ваш комментарий за плохое наказание? =] ... или по крайней мере обрезать его с сайта? – Sniggerfardimungus

ответ

4

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

+0

UM, есть также ссылки (даже если они не применяются в этом случае). – sbi

0

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

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

Слово на именование: Instantiation не является правильным словом в этом случае.

0

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

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

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

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

2

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

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 класс будет иметь возможность создать экземпляр любого типа фруктов добавлены в будущем.

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