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'は多型です。"これを解決するために何をすべきか?すべてが適切に両方のway1とway2でクリーンアップされていますか?なぜ多態型のエラーとクリーンアップの質問ですか?

+2

'main' return型は' void'であってはなりません。 – Mahesh

答えて

7

Baseを多型にするには、少なくとも1つの仮想関数を与える必要があります。

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

クリーンアップに関するご質問について:この場合、最も簡単にはデストラクタだろう技術的
をマップが参照するオブジェクトが前に破壊されているので、両方の方法でいくつかの未定義の動作は、そこにありますポインタはマップから削除されます。これにより、マップが破壊されたときに無効なポインタが含まれ、未定義の動作が発生するという結果になります。
実際には、これは既知のコンパイラで問題を引き起こすことはありません。

それ以外の場合は、すべてを適切にクリーンアップしています。
しかしway2では、単純化することができます。 Baseは仮想デストラクタを持っている場合は、あなただけの動的キャストせずに

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

を行うことができます。

+0

よく書かれた答えをありがとう。私は驚いて、verryはway2で削除行を簡素化できることを嬉しく思っています。だから私は指摘されているオブジェクトの種類に関するすべての情報を知りませんポインタの反対側のオブジェクトをクリーンアップできます。 – alan2here

+0

未参照の振る舞いを参照しない限り、未定義の振る舞いは発生しません。 'map 'はデストラクタやその他のメソッドの 'base * 'ポインタを参照しません。 – aschepler

+0

@aschepler:「左から右への値の変換」が発生するコンテキストで使用されている場合は、ダングリングポインタによってUBが発生します(ただし、通常は悪影響があります)。そのような変換は 'map 'がその内容を破壊するときに起こります。 –