2011-01-09 4 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 '는 다형성 유형이 아닙니다. " 이 문제를 해결하려면 어떻게해야합니까? 모든 것이 올바르게 way1과 way2에서 모두 정리 되었습니까?왜 다형 유형 오류 및 정리 질문?

+2

'main' 리턴 타입은'void'가되어서는 안됩니다. – Mahesh

답변

7

Base을 다형 유형으로 만들려면 하나 이상의 가상 함수를 제공해야합니다. 정리에 대한 질문에 대해서는

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

:이 경우 가장 쉬운 소멸자 것,
기술적으로, 두 가지 방법으로 몇 가지 정의되지 않은 동작이지도는 전에 파괴하기 위해 참조하는 객체 때문에 포인터가 맵에서 제거됩니다. 이로 인해 맵이 소멸 될 때 잘못된 포인터가 포함되어 있으며 정의되지 않은 동작이 발생합니다.
실용적인 목적으로 알려진 컴파일러에서 아무런 문제가 발생하지 않습니다.

그렇지 않으면 모든 것을 올바르게 정리하고 있습니다.
그러나 way2에서는 단순화 할 수 있습니다. Base 가상 소멸자가있는 경우, 당신은 동적 캐스트없이

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

을 할 수 있습니다.

+0

잘 쓰여진 답변 주셔서 감사합니다. 나는 놀랍고 verry는 way2에서 줄을 줄이면된다는 것을 기쁘게 생각합니다. 그래서 포인터의 반대편에있는 객체를 정리할 수 있습니다. 포인터가 가리키는 객체의 유형에 대한 모든 정보를 모릅니다. – alan2here

+0

댕글 링 포인터는 참조 해제되지 않는 한 정의되지 않은 동작을 발생시키지 않습니다. 'map '는 소멸자 또는 다른 방법에서'base * '포인터를 역 참조하지 않습니다. – aschepler

+0

@aschepler : 댕글 링 포인터는 '왼쪽 값과 오른쪽 값 변환'이 발생하는 컨텍스트에서 사용되는 경우 UB를 발생시킵니다 (일반적으로 양성 효과가 있음에도 불구하고). 그러한 변환은'map '이 내용을 파괴 할 때 발생합니다. –