why the polymorphic types error and cleanup questi

2019-06-10 22:36发布

#include <iostream>
#include <string>
#include <map>
#include <vector>

class base {};
class derived1 : public base
{
    public:
        unsigned short n;
        derived1()
        {
            n = 2;
        }
};
class derived2 : public base {};

void main()
{
    // way 1
    {
        std::vector<derived1> a1;
        std::vector<derived2> a2;
        std::map<std::string, base*> b;
        a1.push_back(derived1());
        b["abc"] = &a1.at(0);
        std::cout<<(dynamic_cast<derived1*>(b.find("abc")->second))->n<<std::endl;
    }

    // way 2
    {
        std::map<std::string, base*> b;
        b["abc"] = new derived1();
        std::cout<<dynamic_cast<derived1*>(b.find("abc")->second)->n<<std::endl;
        delete dynamic_cast<derived1*>(b.find("abc")->second);
    }
}

The error is "'dynamic_cast' : 'base' is not a polymorphic type". What should be done to fix this? Is everything properly cleaned up in both way1 and way2?

1条回答
疯言疯语
2楼-- · 2019-06-10 22:56

To make Base a polymorphic type, you need to give it at least one virtual function. The easiest in this case would be the destructor:

class Base {
public:
  virtual ~Base() { }
};

Regarding your question about cleanup:
Technically, there is some undefined behaviour in both ways, because the objects that the map refers to are destroyed before the pointers are removed from the map. This has the result that the map, when it is destructed, contains invalid pointers and that causes undefined behaviour.
For practical purposes, this does not cause any problems with any known compiler.

Otherwise, you are properly cleaning up everything.
But in way2, you can make a simplification. When Base has a virtual destructor, you can just do

delete b.find("abc")->second;

without the dynamic cast.

查看更多
登录 后发表回答