2

I have a Component class, which is the parent class, and for example a Sprite class. Sprite also has various children for animation, but that is not the focus of this question. I also have a component manager which holds a map<string, Component>. I store every component I create in this map. Currently there are 12 types of components, but that will increase.

My Component class has virtual void draw() and update() functions, and the same for Sprite in this case. When I loop through the map of components, however, it only calls the Component draw() and update().

I haven’t really been able to find an answer that has actually worked for me yet.

Jon Purdy
  • 53,300
  • 8
  • 96
  • 166
Baraphor
  • 249
  • 4
  • 16
  • 2
    Are you storing pointers in the map or objects? You really should be storing pointers otherwise you will run into the 'object slicing' problem, which has exactly the symptoms you describe. – jahhaj Jul 31 '12 at 20:42

3 Answers3

1

You’re experiencing object slicing—since your map only stores Component objects by value, those objects do not include any of the information provided by Component subclasses. Generally speaking, subtype polymorphism only works through pointer types, not value types. So you need to store the instances by pointer, preferably std::map<std::string, std::unique_ptr<Component>>:

components["example"] = std::unique_ptr<Component>(new Example());

If you are using a non-C++11 compiler, use std::map<std::string, Component*>:

components["example"] = new Example();

And make sure you delete the Component objects during cleanup, e.g., in the destructor of your component manager. C++03:

for (std::map<std::string, Component*>::const_iterator i = components.begin();
    i != components.end(); ++i)
    delete i->second;

C++11:

for (const auto& i : components)
    delete i.second;
Community
  • 1
  • 1
Jon Purdy
  • 53,300
  • 8
  • 96
  • 166
1

Your problem is quite common, it's called slicing. The map doesn't contain the original objects, it contains copies of the objects. The copy isn't the type that you tried to insert into the map, it's the base type that you declared for the map.

The only way around this is to store pointers rather than the objects themselves. Typically this is using a smart pointer such as shared_ptr so that cleanup is automatic.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
0

Sounds like slicing to me, try storing pointers to your components in the map.

Marcus Riemer
  • 7,244
  • 8
  • 51
  • 76