How to store different classes in the same vector?
So, I have a vector full of all objects for my game; things like player object, enemy object, walls, etc. All things in a vector are children Framework
, so I created a vector type Framework
because that was the closest thing to a generic data type for them.
The problem was that it was not executing overridden functions from the objects it was storing. So I parsed it to find out that I appear to be breaking up objects by storing them as Framework
. So now my question is, how do I keep all these objects in one list?
Just for reference, this is where functions are called that need to be overridden.
for (vector<Framework>::iterator num = gameObjects.begin(); num != gameObjects.end(); ++num)
{
//The current thing
Framework currentObject = *num;
currentObject.frameEvent();
currentObject.frameEndEvent();
currentObject.drawEvent();
}
Thanks in advance.
source to share
You need to keep pointers ( Framework*
) or std::shared_ptr< Framework >
(possibly std::unique_ptr< Framework >
) instances. This allows virtual calls and late binding - this means when you reference your objects, the correct function to call will be determined at runtime. Don't forget to make your functionsvirtual
Then your code (in a similar way)
for (vector< Framework* >::iterator num = gameObjects.begin(); num != gameObjects.end(); ++num)
{
Framework* currentObject = *num;
currentObject->frameEvent();
currentObject->frameEndEvent();
currentObject->DrawEvent();
}
However I would recommend sth like this (C ++ 11 required)
vector< std::unique_ptr< Framework > > gameObjects;
...
for (auto & currentObject : gameObjects)
{
currentObject->frameEvent();
currentObject->frameEndEvent();
currentObject->DrawEvent();
}
The latter (the range for the loop) should work regardless of the type used (as an example, you can use a regular pointer or shared_ptr or unique_ptr).
If you are interested in using unique_ptr
, please note that std::vector
you have to use to store them std::move
, as there can only be one instance std::unique_ptr
(as the name suggests), Consult this answer in case of problems.
source to share
To avoid overlapping objects, you need to use std::vector<Framework*>
or std::vector<std::unique_ptr<Framework>>
(or a smart pointer of your choice).
Sample code:
std::vector<std::unique_ptr<Framework>> gameObjects;
gameObjects.push_back(std::make_unique<Player>(/**/));
gameObjects.push_back(std::make_unique<Wall>(/**/));
And then
for (auto& currentObject : gameObjects)
{
currentObject->frameEvent();
currentObject->frameEndEvent();
currentObject->drawEvent();
}
source to share
Save pointers to Framework
and use polymorphism.
// Base class
class Framework {
// Make pure virtual if nothing is done here.
virtual void frameEvent(); // = 0;
// To ensure the derived instances are deleted properly.
virtual ~Framework(); // = default;
};
// Some specialized class
class SomeObject : public Framework {
void frameEvent() override; // C++11 style override.
};
std::vector<std::unique_ptr<Framework>> objects;
// Add a new SomeObject to the list
objects.emplace_back(new SomeObject());
source to share
Well, the straight answer is you don't. Or you will end up clipping objects that you have already encountered. You need to use the polymorphic capabilities of C ++ and store the common interface of your objects in a vector. Later, you can invoke the desired behavior by calling interface functions that have different implementations according to the actual type of the object.
source to share
You have to make frameEvent
, frameEndEvent
and drawEvent
virtual in Framework
. Then save std::shared_ptr
in your vector:
std::vector<std::shared_ptr<Framework>> objects;
objects.push_back(new GameObject());
for (vector<Framework>::iterator num = gameObjects.begin(); num != gameObjects.end(); ++num)
{
//The current thing
const Framework& currentObject = **num; // reference, don't copy anything if you don't need to
currentObject.frameEvent();
currentObject.frameEndEvent();
currentObject.drawEvent();
}
Note that you can save unique_ptr
to a vector if you are not using operations that require copying elements .
Another option, if you cannot make virtual functions and know what type of objects you are dealing with, you can do the first and then call non-virtual functions:
const PlayerObject& player = static_cast<const PlayerObject&>(*objects[0]);
player.frameEvent();
player.frameEndEvent();
player.drawEvent();
source to share
You need to keep pointers to your objects. If you have C++11
, then ideally you store them with std :: unique_ptr (assuming you have one main vector).
C ++ 03
std::vector<Framework*> gameObjects;
for(std::vector<Framework*>::iterator num = gameObjects.begin();
num != gameObjects.end(); ++num)
{
(*num)->frameEvent();
(*num)->frameEndEvent();
(*num)->drawEvent();
}
C ++ 11
std::vector<std::unique_ptr<Framework>> gameObjects;
for(auto& num: gameObjects)
{
num->frameEvent();
num->frameEndEvent();
num->drawEvent();
}
source to share