デストラクタを非公開にすることの用途は何ですか?
9 に答える
基本的に、クラスのオブジェクトのライフサイクルを他のクラスに任せたいとき、またはオブジェクトの破壊を防ぐ理由があるときはいつでも、デストラクタを非公開にすることができます。
たとえば、ある種の参照カウントを行っている場合、オブジェクト (または「フレンド」化されたマネージャー) にそれ自体への参照数をカウントさせ、数がゼロになったら削除することができます。プライベート dtor は、それへの参照がまだある場合、他の誰かがそれを削除するのを防ぎます。
別の例として、データベース接続が開かれている、ファイルが書き込まれているなど、プログラムの他の条件に応じて、オブジェクトを破棄するか、破棄を拒否するマネージャー (またはそれ自体) を持つオブジェクトがある場合はどうでしょう。クラスまたはマネージャーに「request_delete」メソッドを含めることができます。このメソッドはその条件をチェックし、削除または拒否し、それが何をしたかを示すステータスを返します。これは、「削除」を呼び出すよりもはるかに柔軟です。
このようなオブジェクトはスタック上に作成できません。常にヒープ上。また、削除は友達またはメンバー経由で行う必要があります。製品は、単一のオブジェクト階層とカスタム メモリ マネージャーを使用する場合があります。このようなシナリオでは、プライベート 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;
}
ユーザーがデストラクタにアクセスできないようにする場合、つまり、オブジェクトを他の方法でのみ破棄する場合。
http://blogs.msdn.com/larryosterman/archive/2005/07/01/434684.aspxは、オブジェクトが参照カウントされ、カウントがゼロになったときにオブジェクト自体によってのみ破棄される例を示しています。
COM は、この戦略を使用してインスタンスを削除します。COM はデストラクタを非公開にし、インスタンスを削除するためのインターフェイスを提供します。
Release メソッドの例を次に示します。
int MyRefCountedObject::Release()
{
_refCount--;
if ( 0 == _refCount )
{
delete this;
return 0;
}
return _refCount;
}
ATL COM オブジェクトは、このパターンの代表的な例です。
ここにすでに存在する回答に追加します。プライベート コンストラクターとデストラクタは、作成されたオブジェクトをヒープに割り当てる必要があるファクトリを実装する際に非常に役立ちます。一般に、オブジェクトは静的メンバーまたはフレンドによって作成/削除されます。典型的な使用例:
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
}
クラスは単独でのみ削除できます。参照カウント オブジェクトの試行を作成する場合に便利です。その後、 release メソッドのみがオブジェクトを削除できるため、エラーを回避できる可能性があります。
あなたがプライベートデストラクタについて尋ねていたことは知っています。これが私が保護されたものを使用する方法です。アイデアは、メインに余分な機能を追加するクラスへのポインタを介してメイン クラスを削除したくないということです。
以下の例では、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(){}
};
ダークジェントリーは間違っています。スタック上に作成されたプライベート 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
各モジュールがデバッグヒープなどの異なるヒープを使用できる Windows の問題に対処する方法かもしれません。その問題が正しく処理されないと、悪いこと が起こる可能性があります。