ref_object(解体オブジェクト)




オブジェクトを生成するにはnewやnew [ ]とは限りません。

もっと別の手段で生成されているかも知れません。それぞれの生成に応じて、解体手段が必要になってきます。また、解体するときに、何かの終了メソッドを呼び出したい場合もあるかも知れません。

smart_ptrを使う場合、smart_ptrに保持させるオブジェクトの解体手段を定義することが出来ます。

これは、ref_object(YTL/ref_deleter.hで定義されている)を派生させて、delete_instanceをオーバーライドします。

ディフォルトで、nonarray_ref_object(非配列オブジェクトの解体するためのテンプレート)、array_ref_object(配列を解体するためのテンプレート)が用意されていますので、そちらも参考にしてください。

smart_ptrに、オブジェクトの所有権を委任するのは、Add,AddArrayというメソッドがあります。これらは、

枠-1
    smart_ptr<CHoge> hoge;
    hoge.Add(new CHoge);                //  非配列
    hode.AddArray(new CHoge[10],10);    //  配列


のように使います。(smart_ptrは、このように、配列、非配列のポインタ、両方を扱うことが出来ます)

このAdd,AddArrayには、第2,第3パラメータで、ref_objectを指定できます。

枠-2
    //  非配列オブジェクトを持たせる
    template <class S>
    void    Add(S*_P,ref_object*ref);

    //  配列オブジェクトを持たせる
    template <class S>
    void    AddArray(S*_P,int n=INT_MAX,ref_object*ref=NULL);


このref_objectを指定してある場合は、通常のdeleteやdelete [ ]ではなく、ref_object::delete_instanceが呼び出されます。ここで独自の終了処理を記述することができるわけです。

すなわち、smart_ptrは、単に参照カウント方式のポインタではなく、自己の保有するオブジェクトの解体手段まで完全に知っているポインタなのです。

例)解体時に、特定のメソッドを呼び出すことのできる解体子(YTL/ref_callback_deleter.hで定義されている)

list-1
template<class T>
class nonarray_callback_ref_object : public ref_object {
/**
        非配列オブジェクトをdeleteするためのテンプレート
        解体時(解体後)にコールバックもしてくれる
        class ref_object class function_callback も参照のこと

        //  使用例
        smart_ptr<CSound> s;
        CSound* sound = new CSound;
        smart_ptr<function_callback>
            func(function_callback_v::Create(&test));
        s.Add(sound,new nonarray_callback_ref_object<CSound>(sound,func));
        ↑このsmart_ptr<CSound>は、解体時(解体後)にtest関数が呼び出される
*/
public:
    nonarray_callback_ref_object(T* p,const smart_ptr<function_callback>& func)
        : m_p(p),m_func(func) {}
    virtual void    delete_instance() {
        delete m_p;
        m_func->run();
    }
private:
    T* m_p; //  削除すべきアドレスを保持しておく
    smart_ptr<function_callback> m_func;
    //  ↑汎用コールバックテンプレート
};

//  任意の配列をdeleteするためのテンプレート
template<class T>
class array_callback_ref_object : public ref_object {
/**
        任意の配列をdeleteするためのテンプレート
        解体時(解体後)にコールバックもしてくれる
        class ref_object class function_callback も参照のこと

*/
public:
    array_callback_ref_object(T* pa,const smart_ptr<function_callback>& func)
        : m_pa(pa),m_func(func) {}
    virtual void    delete_instance() {
        delete [] m_pa;
        m_func->run();
    }
private:
    T* m_pa;    //  削除すべきアドレスを保持しておく
    smart_ptr<function_callback> m_func;
    //  ↑汎用コールバックテンプレート
};