web-dev-qa-db-ja.com

デストラクタをプライベートとして使用することは何ですか?

デストラクタをプライベートとして使用することは何ですか?

179
yesraaj

基本的に、他のクラスにクラスのオブジェクトのライフサイクルを担当させたい場合、またはオブジェクトの破壊を防ぐ理由がある場合はいつでも、デストラクタをプライベートにすることができます。

たとえば、何らかの参照カウントを行う場合は、オブジェクト(または「フレンド」になっているマネージャー)にそれ自体への参照の数をカウントさせ、数がゼロになったら削除するようにすることができます。プライベートdtorは、まだ参照されている場合、他の人がそれを削除できないようにします。

別の例として、データベース接続が開いている、ファイルが書き込まれているなど、プログラムの他の条件に応じて、オブジェクトを破棄するか、破棄することを拒否するマネージャー(またはそれ自体)を持つオブジェクトがある場合はどうなりますか?クラスまたはマネージャーに「request_delete」メソッドを設定して、その条件をチェックすると、削除または拒否され、その処理内容を示すステータスが返されます。 「削除」を呼び出すよりもはるかに柔軟です。

165
Paul Tomblin

そのようなオブジェクトはスタック上に作成できません。常にヒープ上。また、削除は友人またはメンバーを介して行わなければなりません。製品は単一のオブジェクト階層とカスタムメモリマネージャーを使用する場合があります。このようなシナリオではプライベートdtorを使用する場合があります。

#include <iostream>
class a {
    ~a() {}
    friend void delete_a(a* p);
};


void delete_a(a* p)  {
    delete p;
}

int main()
{
    a *p = new a;
    delete_a(p);

    return 0;
}
65
dirkgently

ユーザーがデストラクタにアクセスしないようにする場合、つまり、オブジェクトを他の方法でのみ破棄する場合。

http://blogs.msdn.com/larryosterman/archive/2005/07/01/434684.aspx は、オブジェクトが参照カウントされ、オブジェクト自体によってのみ破棄される必要がある場合の例を示しますカウントはゼロになります。

44
Michael

COMは、この戦略を使用してインスタンスを削除します。 COMはデストラクタをプライベートにし、インスタンスを削除するためのインターフェイスを提供します。

Releaseメソッドがどのように見えるかの例を次に示します。

int MyRefCountedObject::Release() 
{
 _refCount--;
 if ( 0 == _refCount ) 
 {
    delete this;
    return 0;
 }
 return _refCount;
}

ATL COMオブジェクトは、このパターンの代表的な例です。

16
Vinay

ここにすでに存在する回答に追加します。プライベートコンストラクタとデストラクタは、作成されたオブジェクトをヒープに割り当てる必要がある factory を実装する際に非常に役立ちます。一般に、オブジェクトは静的メンバーまたは友人によって作成/削除されます。典型的な使用例:

class myclass
{
public:
    static myclass* create(/* args */)  // Factory
    {
        return new myclass(/* args */);
    }

    static void destroy(myclass* ptr)
    {
        delete ptr;
    }
private:
    myclass(/* args */) { ... }         // Private CTOR and DTOR
    ~myclass() { ... }                  // 
}

int main ()
{
    myclass m;                          // error: ctor and dtor are private
    myclass* mp = new myclass (..);     // error: private ctor
    myclass* mp = myclass::create(..);  // OK
    delete mp;                          // error: private dtor
    myclass::destroy(mp);               // OK
}
8
nav

クラスはそれ自体でのみ削除できます。参照カウントオブジェクトの試行を作成する場合に役立ちます。その場合、オブジェクトを削除できるのはreleaseメソッドのみであり、おそらくエラーの回避に役立ちます。

6
Roland Rabien

私はあなたが私的な破壊者について尋ねていたことを知っています。保護されたものを使用する方法は次のとおりです。アイデアは、メインに追加機能を追加するクラスへのポインターを介してメインクラスを削除したくないということです。
以下の例では、HandlerHolderポインターを使用してGuiWindowを削除したくありません。

class Handler
{
public:
    virtual void onClose() = 0;
protected:
    virtual ~Handler();
};

class HandlerHolder
{
public:
    void setHandler( Handler* );
    Handler* getHandler() const;
protected:
    ~HandlerHolder(){}
private:
    Handler* handler_;
};

class GuiWindow : public HandlerHolder
{
public:
    void finish()
    {
        getHandler()->onClose();
    }

    virtual ~GuiWindow(){}
};
3
Mykola Golubyev

ひどく間違っています。スタック上に作成されたプライベートc-torおよびd-torを持つオブジェクトの例を次に示します(ここでは静的メンバー関数を使用していますが、フレンド関数またはフレンドクラスでも同様に実行できます)。

#include <iostream>

class PrivateCD
{
private:
    PrivateCD(int i) : _i(i) {};
    ~PrivateCD(){};
    int _i;
public:
    static void TryMe(int i)
    {
        PrivateCD p(i);
        cout << "inside PrivateCD::TryMe, p._i = " << p._i << endl;
    };
};

int main()
{
    PrivateCD::TryMe(8);
};

このコードは出力を生成します:PrivateCD :: TryMeの内部、p._i = 8

3
misicd

これは、各モジュールが Debug heapなどの異なるヒープを使用できるWindowsの問題に対処する方法かもしれません。その問題が正しく処理されない場合 badthings が発生する可能性があります。

2
Jared Oberhaus