2009-07-07 6 views
0

私はデータ(例えばD)をオブジェクト(例えばO)に関連付けるクラス(例えばC)を作成しています。 Oが破壊されると、OはCにすぐには存在しなくなることをCに通知します。(...その後、Cが適切な時間であると感じると、CはOに属するもの、すなわちDを放棄します。オブジェクトが存在しなくなった後、オブジェクトに関連付けられたデータをどのように破棄するのですか?

If Dはどんなタイプのオブジェクトでもかまいませんが、Cが "delete D;"を実行するための最良の方法は何ですか?そしてDがオブジェクトの配列である場合はどうなりますか?

私の解決策は、

voidポインタを格納してdeleteを呼び出すことも考えましたが、これは未定義の動作であり、呼び出さないことがわかりました。私はテンプレートが斬新な解決策であると考えましたが、私はその考え方をうまく働かすことができませんでした。

は、ここで私はCのために、これまで持っているものだ、マイナスいくつかの詳細:


// This class is C in the above description. There may be many instances of C. 
class Context 
{ 
public: 
    // D will inherit from this class 
    class Data 
    { 
    public: 
     virtual ~Data() {} 
    }; 

    Context(); 
    ~Context(); 

    // Associates an owner (O) with its data (D) 
    void add(const void* owner, Data* data); 

    // O calls this when he knows its the end (O's destructor). 
    // All instances of C are now aware that O is gone and its time to get rid 
    // of all associated instances of D. 
    static void purge (const void* owner); 

    // This is called periodically in the application. It checks whether 
    // O has called purge, and calls "delete D;" 
    void refresh(); 

    // Side note: sometimes O needs access to D 
    Data *get (const void *owner); 

private: 
    // Used for mapping owners (O) to data (D) 
    std::map _data; 
}; 

// Here's an example of O 
class Mesh 
{ 
public: 
    ~Mesh() 
    { 
     Context::purge(this); 
    } 

    void init(Context& c) const 
    { 
     Data* data = new Data; 

     // GL initialization here 

     c.add(this, new Data); 
    } 

    void render(Context& c) const 
    { 
     Data* data = c.get(this); 
    } 

private: 
    // And here's an example of D 
    struct Data : public Context::Data 
    { 
     ~Data() 
     { 
      glDeleteBuffers(1, &vbo); 
      glDeleteTextures(1, &texture); 
     } 

     GLint vbo; 
     GLint texture; 
    }; 
}; 

P.S.あなたがコンピュータグラフィックスやVRに慣れているならば、オブジェクトごとのコンテキストデータ(OpenGL VBO IDなど)をアプリケーションごとのデータ(頂点の配列など)から分離し、コンテキストごとに解放するクラスを作成しています(該当するレンダリングコンテクストが現在のものである)適切な時点でのデータ。

+0

ありがとうございます。 私のプログラムには、更新スレッドとレンダリングスレッドがあります。レンダリングスレッドは、各目に対してステレオ画像を作成するために2回レンダリングを担当します。各3DオブジェクトOは、各コンテキスト(すなわち、O毎に2つのDのコピーがある)について目に特有のレンダリングデータDを有する。 問題:更新スレッドでOを作成または破棄することはできますが、Oの目に固有のレンダリングデータは、レンダリングスレッドで破棄する必要があります。 Cは、レンダリングスレッドでDの両方のインスタンスを破壊することがわかるように、Oが破壊されているかどうかを知る必要があります。 –

答えて

1

質問要件についてはあまりにも漠然としているので、良い具体的な答えを出すのは難しいです。私は、

所有者が死亡したときにデータがすぐに消滅するようにするには、所有者に削除を依頼します(Cインスタンスに認識させる必要がある場合はCに通知します)。あなたが余分な時間に削除を行うようにしたいのであれば、あなたのソリューションは上手く見えます。データから派生することは、私には正しいことだと思われます。 (もちろん、あなたが行ったように〜Data()がバーチャルであることが重要です)

Dがオブジェクトの配列の場合はどうなりますか?この質問には2つの解釈があります。 Dが常に配列であることを意味するならば、それはDataへのポインタの配列(またはベクトル<>)にします。次に、C :: purge()でベクトルを歩き、オブジェクトを削除します。 Dがオブジェクトの配列であるかもしれないが、単一のオブジェクトでもあり得るということを意味するなら、2つの方法があります。それは、常に配列(サイズ1の可能性があります)であるか、実際のオブジェクト(またはそのポインタ)の配列をラップするクラスである単一のオブジェクト(Dataから派生したもの)であると判断します。後者の場合、ラッパークラスのデストラクタは配列をウォークして削除を行う必要があります。配列(またはベクトル<>)にポインタではなく実際のオブジェクトが含まれるようにする場合(その場合、配列を移動して手動で削除する必要はありません)、次の制限があります。 1.配列内のすべてのオブジェクトは、同じ実際の型でなければなりません。 2.配列をその型に宣言する必要があります。これはあなたに多形のすべての恩恵を失うでしょう。

1

あなたが探しているのは、Boost::shared_ptrなどのスマートポインタシステムです。

0

、質問に答えるために、私はベクトル<をお勧めしたい>が、あなたはDと関連付ける必要があるだろう「Dは、オブジェクトの配列でたら?」:

 
struct D_vector 
    :D 
{ 
    vector<whatever> vw; 
}; 
関連する問題