Std :: map cannot handle polymorphism?

When using std :: map in C ++, is it possible to store inherited classes as its "base class" on the map and still be able to call their overloaded methods? See this example:

#include <iostream> #include <map> class Base { public: virtual void Foo() { std::cout << "1"; } }; class Child : public Base { public: void Foo() { std::cout << "2"; } }; int main (int argc, char * const argv[]) { std::map<std:string, Base> Storage; Storage["rawr"]=Child(); Storage["rawr"].Foo(); return 0; } 

This following code writes "1". Something tells me that polymorphism does not work when you use std :: map.

+4
source share
5 answers

Polymorphism does not work in this case, because std :: map saves Base as a value type, so objects are sliced .

If you want to have polymorphism on stored objects, you need to save pointers or use one of boost ptr container for the same. This means that you need to remember to delete memory after that (please do not put pointers to objects on the map)

+15
source

His case is Object Slicing . Try pasting pointers.

If there is inheritance, copying leads to cutting. That is, if you create a map of objects of the base class and try to insert objects of the derived class into it, the derivative of the objects will be deleted as objects are copied (through the copy constructor of the base class).

Therefore, it is recommended that you use pointers, not the copies themselves.

+3
source

The first idea is that to get the polymorphism you need to call the member method by pointer or link. I would save the pointer to the base class on the map (the stored item will be copied), and then call it using the pointer as follows:

 #include <iostream> #include <map> class Base { public: virtual void Foo() { std::cout << "1"; } }; class Child : public Base { public: void Foo() { std::cout << "2"; } }; int main (int argc, char * const argv[]) { std::map<std::string, Base*> Storage; Storage["rawr"] = new Child(); Storage["rawr"]->Foo(); return 0; } 

You get the result "2".

Note. Now you have to take care of the allocated memory.

+1
source

Dynamic polymorphism only works with links and pointers. In the case of using containers that copy objects inside them - only with pointers.

If you force a cast from super-type to base-type without using a pointer or reference, the object's memory will be sliced . Check it out: Wiki objects clipping objects

+1
source

No, you have to keep the pointer to the base class to get polymorphic behavior. The way you do it now will lead to slicing .

0
source

All Articles