views:

96

answers:

4

I am currently working on a 2D game project and I want to switch from Delphi to C++.

In Delphi, I could declare an array which had the type of a class Entity, and I could put Entitys as well as objects of classes which are derived from Entity into it.

This would be very important for me, as it seems logical that all entities should be stored and managed in one place.

  • Is this possible in C++?
  • (Why not if it is in Delphi?)

  • What other choices to achieve something similar do I have?

I would need to do something like below:

#include <vector>
using namespace std;

class Entity
{
public:
 int id;
};

class Camera : Entity
{
public:
 int speed;
};

int main()
{
 Entity point;
 Camera camera;

 vector<Entity> vec;

 vec.push_back( point );
 vec.push_back( camera ); //Why can't I do that?
}

I hope I have made myself clear enough and I'd really appreciate your help

+5  A: 

Use a boost::ptr_vector&lt;Entity> to store polymorphic objects, or a container of smart pointers, e.g. vector<boost::shared_ptr<Entity> >, if you need to share/move them elsewhere.

Roger Pate
A: 

I guess you are looking for C++ templates.

thelost
How would templates help? Fred wants to store objects of two different types (related by inheritance).
Roger Pate
+5  A: 

...Because (without further modifiers) all C++ types are value types, speaking in terms of Delphi or C#. You are basically doing this:

 point = camera;

This statement invokes the compiler generated assignment operator:

Entity& Entity::operator(const Entity& pOther) ...

This works, since const Camera& is convertible to const Entity&. But inside the assignment there is no information about the 'Camera' part of the object, the pOther gets 'sliced' into Entity object. You get the required behaviour by telling the C++ compliler that you want to treat the objects as reference types (pointers):

int main() 
{ 
 vector<std::shared_ptr<Entity> > vec; 

 vec.push_back( std::shared_ptr<Entity>(new Point) ); 
 vec.push_back( std::shared_ptr<Entity>(new Camera) );
}
paul_71
+1  A: 

Your problem is that you are mixing the way Delphi and C++ deal with objects.

In C++ case a class instance can be used in three ways:

  • as a value
  • as a reference
  • as a pointer

Only the two last ways express the same behaviour as you would expect from Delphi code.

In your example, you are creating value objects, this means that when you try to assign a Camera to an Entity, the sub part of Entity that belongs to Camera gets copied, but nothing else.

You should change your code to use pointers instead,

int main()
{
 Entity* point = new Entity;
 Camera* camera = new Camera;

 vector<Entity*> vec;

 vec.push_back( point );
 vec.push_back( camera );

 // don't forget to delete them, when you're done with the list
 for (vector<Entity*>::iterator iter = vec.begin(); iter != vec.end(); ++iter)
     delete (*iter);
}
enter code here

To avoid messing with pointers directly, a more modern C++ idiom is to make use of smart pointers. As shown by paul_71's answer.

Paulo Pinto