デストラクタをプライベートにすることの用途は何ですか?


回答:


176

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

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

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


73

このようなオブジェクトをスタック上に作成することはできません。常にヒープ上。そして、削除は友人やメンバーを介して行われる必要があります。製品では、単一のオブジェクト階層とカスタムメモリマネージャーを使用できます。このようなシナリオでは、プライベート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;
}

19
修正:そのようなオブジェクトはスタック上に作成できます(ただし、フレンドまたは自分自身のスコープ内でのみ)。
Thomas Eding、2014年

さらに、ホストされた実装で静的またはグローバルオブジェクト(つまり、「静的ストレージ期間」を持つ)を使用することはできません(デストラクタはプログラムの終了時に呼び出されるため)。
ピーター-モニカを

45

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

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


17

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

次に示すのは、Releaseメソッドの例です。

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

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


8

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

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
}

7

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


3

私はあなたが民間の破壊者について尋ねていたのを知っています。これが保護されたものの使い方です。アイデアは、メインに追加の機能を追加するクラスへのポインターを通じてメインクラスを削除したくないということです。
以下の例では、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

ひどく間違っています。これは、スタック上に作成されたプライベート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
、あなたのクラスを使用するコードがスタック上でクラスをインスタンス化できないことを暗示しています。もちろん、そのコンテキストではプライベートメンバーにアクセスできるため、クラスメソッド内でスタック上のクラスをインスタンス化することもできます。
Edward Loper、2011年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.