开发者

Dynamic instantiation in C++

I want my code to be extensible, in a way where at runtime I create the objects.

For example, let's say I have a Grocery class which has an array of fruits and I want to fill this array of fruits with objects which derives from fruits.

cl开发者_开发问答ass Fruit{

};

class Grocery{

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

class Apple: Fruit{

};

class Pineapple: Fruit{

};

Now at runtime I want my Grocery class vector m_fruits to be filled with class objects of Apple and Pineapple. So is it possible in some way.

if I add another fruit as strawberry in future, its object will be created and added to the vector of Grocery dynamically without changing the implementation of Grocery class?

Code help will be appreciated.


Check your textbook. It probably mentions that you can only treat pointers to types polymorphically. In other words, a vector of pointers to fruit can take pointers to apples or pineapples.


Well, if you want to make it so your Grocery class can generate any type of fruit. Even fruit that has been implemented after the grocery class has been locked away, I suppose you might be after something like the following?

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");

And that way your Grocery class will be able to instantiate any type of fruit added in the future.


Assum that Fruit has pure virtual functions (denoted by virtual func() = 0) you would need to store pointers to Fruit objects inside your vector std::vector<Fruit*>.

Unfortunately standard containers aren't particulary good at handling pointers and you will have to delete all objects inside your vector in the destructor of your Grocery. You might consider shared_ptr from TR1 or the boost library.

A word on naming: Instantiation isn't the proper word in this case.


You cannot store objects of a derived type by value in any container of a base type without object slicing occuring.

You need to do one of the following:

  1. Use a vector of raw pointers to the base type, e.g. std::vector<Fruit*> and manage the lifetime of the individual Fruit instances yourself (this is the least desirable option).
  2. Use a vector of smart pointers to the base type, e.g. std::vector<boost::shared_ptr<Fruit> >, and allow reference counting to manage the individual items' lifetimes.
  3. Use boost::ptr_vector<Fruit> to store the items, and the items' lifetime are bound to that of the containing ptr_vector.

Depending on your need, #2 & #3 are preferable. #1 should be avoided, as it involves manual effort to manage the lifetimes and could easily result in memory leaks if done incorrectly.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜