2011-01-09 2 views
0
#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 и way2?Почему проблема с полиморфными типами и вопрос очистки?

+2

'main' return type не должен быть' void'. – Mahesh

ответ

7

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

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

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

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

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

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

+0

Спасибо за хорошо написанный ответ. Я удивлен и доволен, что я могу упростить строку delete2. Поэтому я могу очищать объекты с другой стороны указателей, где я не знаю всей информации о типе объекта, на который указывают. – alan2here

+0

Висячие указатели не вызывают неопределенное поведение, если они не разыменованы. И 'map ' не разыменовывает никаких своих указателей 'base * 'в своем деструкторе или любом другом методе. – aschepler

+0

@aschepler: Висячие указатели также вызывают UB (хотя и с типично мягкими эффектами), если они используются в контексте, где происходит преобразование «lvalue-to-rvalue». Такое преобразование происходит, когда 'map ' разрушает его содержимое. –

Смежные вопросы