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.

+3


source to share


8 answers


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.

+7


source


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();
}

      

+2


source


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

      

+2


source


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.

+1


source


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

      

+1


source


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();
}

      

+1


source


Store pointers in your vector instead of actual instances.

0


source


Another, possibly faster approach is to store them in separate vectors. This can be 50 times faster due to the higher caching efficiency.

0


source







All Articles