std::map unable to handle polymorphism?

前端 未结 5 597
时光说笑
时光说笑 2021-01-18 23:38

When using std::map in c++, is it possible to store inherited classes as their \"base class\" in the map and still being able to call their overloaded methods? See this exam

相关标签:
5条回答
  • 2021-01-18 23:58

    Polymorphism doesn't work in that case because the std::map stores the Base as a value type, so the objects get sliced.

    If you want to have polymorphism on stored objects, you need to store pointers or use one of the boost ptr containers to effect the same. This means you need to remember to delete the memory afterwards (please don't put pointers to stack objects into the map)

    0 讨论(0)
  • 2021-01-19 00:04

    Dynamic polymorphism works only with references and pointers. In case of using containers, which copy objects around inside them -- only with pointers.

    If you would force a cast from super type to base type without using pointer or reference, the object memory would be sliced. Check this out: Object slicing wikipedia article

    0 讨论(0)
  • 2021-01-19 00:06

    No, you must store a pointer to the base class to get the polymorphical behavior. The way you do now will lead to slicing.

    0 讨论(0)
  • 2021-01-19 00:07

    Its case of Object Slicing. Try to insert with pointers.

    In the presence of inheritance copying leads to slicing. That is, if you create a map of base class objects and you try to insert derived class objects into it, the derivedness of the objects will be removed as the objects are copied (via the base class copy constructor) into the map.

    Hence, it is recommended to use pointers rather than copies itself.

    0 讨论(0)
  • 2021-01-19 00:18

    First idea is that to get polymorphism you need to call member method on pointer or reference. I would store pointer to base class in the map (the element that you store gets copied) and then call via pointer like this:

    #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 result "2".

    Note: You have to take care of the allocated memory now.

    0 讨论(0)
提交回复
热议问题