2011-06-22 13 views
4

C++マップを使用して、基本クラスと派生クラスへのポインタを格納する際に問題があります。実行時にstd :: map、polymorphism and delete

#include <map> 
#include <iostream> 

struct foo{ int dummy[4]; }; 
struct bar{ int additionnal[4]; }; 

class Base 
{ 
private: 
    struct foo *_internal_structure; 
public: 
    Base() { _internal_structure = new struct foo; } 
    ~Base() 
    { 
     delete _internal_structure; 
     std::cout << "Base DTOR\n"; 
    } 
}; 

class Derived: public Base 
{ 
private: 
    struct bar *_additional_structure; 
public: 
    Derived() { _additional_structure = new struct bar; } 
    ~Derived() 
    { 
     delete _additional_structure; 
     std::cout << "Derived DTOR\n"; 
    } 
}; 


int main(int argc, char *argv[]) 
{ 
    std::map<int, Base*> my_map; 
    Base *to_add = new Base(); 
    Derived *derived_to_add = new Derived(); 
    my_map[1] = to_add; 
    my_map[2] = derived_to_add; // works, derived class, but object gets sliced 

    /// clear hash map /// 
    std::map<int, Base*>::const_iterator iter; 
    for(iter = my_map.begin(); iter != my_map.end(); ++iter) 
    { 
     delete (*iter).second; 
    } 

    return 0; 
} 

結果:

私はかなり長いが、簡単なコードで説明しましょう

Base DTOR 
Base DTOR 

だから、私は私のマップに派生クラスポインタを挿入する事は、あります基礎となるオブジェクトはBaseクラスとみなされます。そのため、呼び出されるデストラクタは、Derivedクラスではなく、Baseクラスの1つです。 Valgrindは私が毎回16バイトを失うことを確認します。

また、私はブーストのshared_ptrのI saw some mentions of it here)を使用することはできませんし、私が使用埋め込まれたアーキテクチャでは、C++例外と(私の場合には、いくつかのアンアラインドアクセスやその他の悪いものが発生する)RTTI をサポートしていません。 (編集:関連しません)。

この動作をどのように修正できるかご存知ですか?

+0

あなたの質問には関係ありませんが、それらのデータメンバはplainの代わりに 'boost :: scoped_ptr'または' const std :: auto_ptr'ポインタ。 –

+0

@Tadeusz:私はブーストを使用することはできません、私は最後の段落でそれを言う:)私はauto_ptr、おかげで調べます。 – Gui13

+0

最新のコンパイラには、Boostから新しいC++標準に伝えられているものがあります。現在のVisual C++(あるいはGCCと思っています)の場合は、 'std :: unique_ptr'または' std :: shared_ptr'を参照してください。 –

答えて

13

仮想デストラクタはどこですか?

Read thisおよびが忘れています。実際には、あなたは10のC++命令のうちの1つを壊しただけです...)

+0

+1。決して赤でもないはずです。:) –

+0

@Vlad:もし私がそれを赤にするための適切な構文を知っていれば、 –

+0

ハハハ、それはおかげできです:) – Gui13

6

任意の基本クラスのデストラクタは、仮想である必要があります。

それ以外の場合は、実行時に、サブクラスが基本クラスへのポインタによって参照される場合に、実際に呼び出されるデストラクターを特定することは不可能です。

関連する問題