Shreyas
Shreyas

Reputation: 708

Vector of base and inherited objects

How would one go about creating a vector that includes both the base class as well as any derived classes?

For example, in a chess engine, I currently have a Move class which stores a particular move and a few functions to help it. In order to save memory, as millions of these objects are going to be created, I also have a derived class CaptureMove that extends the Move class storing a bit more information about what and where the piece was captured.

From what I can gather, pointers to Move objects should work, but I'm not quite sure on how to go about it.

Upvotes: 0

Views: 919

Answers (1)

Christophe
Christophe

Reputation: 73366

The question is quite broad. Here some ideas:

Vectors of base pointers:

This works extremely well if your class is polymorphic (i.e. the relevant functions of the base class are virtual).

vector<Move*> mp; 
mp.push_back (new Move);     // attention, you have to delete it ofr memory will leak
mp.push_back (new CaptureMove);

It the simplest way to proceed. However you have to make sure that when you add an object, it's allocated properly (e.g. created with new), and that once you no longer need it, you delete it. This can be very cumbersome, especially if vector was copied and some of its pointers are still in use.

This approach can be practical for example if you create and delete the objects in a centralised manner, so that the vector only uses pointers which are properly managed somewhere else.

Vector of shared base pointers:

vector<shared_ptr<Move>> m; 
m.push_back(make_shared<Move>());
m.push_back(make_shared<CaptureMove>());
m.push_back(make_shared<Move>());

Here an online demo.

It extends the pointer solution, using smart pointers to take care of the release of unused objects.

Honestly, it's a little overhead but it's really worth it, in order to have reliable code. This is the approach I would take personnally if I'd have to do it.

Vector of compound object

You could also prefer to store the object instead of a pointer to the object. While the idea seems simple, it's more difficult to do, because different derivates could have different size. And it has serious drawbacks, because you'd need to know all possible base and derived types you may store in the vector, which makes this approach less flexible.

You could certainly manage this with a complex union, but the easiers way would be to use boost::variant.

vector<boost::variant<Move, CaptureMove>> m; 

This approach is only worth considering if the number of derived classes is very limited, but you have huge numbers of small objects (so that memory allocation would become a real overhead) of almost the same size.

Upvotes: 1

Related Questions