почему ошибка полиморфных типов и вопрос очистки? - PullRequest
0 голосов
/ 09 января 2011
#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);
    }
}

Ошибка: «dynamic_cast:« base »не является полиморфным типом».Что нужно сделать, чтобы это исправить?Все ли правильно вычищено в обоих направлениях1 и 2?

1 Ответ

7 голосов
/ 09 января 2011

Чтобы сделать Base полиморфным типом, вам нужно дать ему хотя бы одну виртуальную функцию. Самым простым в этом случае будет деструктор:

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

Относительно вашего вопроса об уборке:
Технически, есть некоторое неопределенное поведение в обоих направлениях, потому что объекты, на которые ссылается карта, уничтожаются до того, как указатели будут удалены с карты. Это приводит к тому, что карта, когда она разрушена, содержит недопустимые указатели, что приводит к неопределенному поведению.
В практических целях это не вызывает проблем ни с одним известным компилятором.

В противном случае вы все правильно очищаете.
Но в way2 вы можете сделать упрощение. Когда Base имеет виртуальный деструктор, вы можете просто сделать

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

без динамического приведения.

...