17

仮想デストラクタのほとんどすべてのコードスニペットには、次のようなパブリックメンバー関数として含まれていることがわかります。

class Base
{
public:
    virtual ~Base()
    {
        cout << "~Base()" << endl;
    }
};
class Derived : public Base
{
public:
    ~Derived()
    {
        cout << "~Derived()" << endl;
    }
};

仮想デストラクタはパブリックである必要がありますか、それとも非パブリックの仮想デストラクタが理にかなっている状況がありますか?

4

5 に答える 5

21

仮想デストラクタはパブリックである必要がありますか、それとも非パブリックの仮想デストラクタが理にかなっている状況がありますか?

コースのための馬。多態的な削除が必要な場合は仮想デストラクタを使用し、publicそうでない場合はデストラクタを仮想にする必要はありません。

ハーブのアドバイスに従ってください:

ガイドライン#4:基本クラスのデストラクタは、パブリックで仮想、または保護されて非仮想である必要があります。

簡単に言うと、2つの状況のいずれかが残ります。また:

  1. ベースポインタを介した多態的な削除を許可する必要があります。この場合、デストラクタは仮想でパブリックである必要があります。また
  2. そうしないでください。この場合、デストラクタは非仮想で保護されている必要があります。後者は、不要な使用を防ぐためです。
于 2013-03-20T10:11:29.497 に答える
6

非仮想デストラクタと同じように、そうである必要はありませんがpublic、ほとんどの場合はそうです。

クラスがルールの例外であり、何らかの理由でインスタンスの存続期間を制御する必要がある場合、デストラクタは非である必要がありますpublic。これは、クライアントがクラスのインスタンスを利用できる(または利用できない)方法に影響しますが、もちろんそれが全体のポイントです。また、デストラクタはvirtualであるため、他のオプションは。だけvirtual protectedです。

関連:保護されたデストラクタを仮想化するための使用法はありますか?

于 2013-03-20T09:58:58.330 に答える
2

特別なメソッド(たとえば、作成/破棄)を使用してオブジェクトを作成/破棄する場合は、その必要はありません。ただし、スタックまたはヒープ上にオブジェクトを作成する場合は、パブリックデストラクタが必要です。

于 2013-03-20T09:58:23.913 に答える
1

ここでの質問は仮想デストラクタに関するものです。したがって、そのような実装が必要な理由の順列には、継承の場合も含める必要があると思います。質問に対する答えは、以下によって異なります。

1)クラスをインスタンス化したくない場合は、プライベートコンストラクタ/デストラクタを使用できます。ただし、インスタンス化は同じクラスの別のメソッドで実行できます。したがって、クラス内でMyDestructor()などの特定のメソッドを使用してデストラクタを呼び出す場合でも、デストラクタをプライベートにすることができます。例:シングルトンデザインパターン。また、この場合、クラスが継承されるのを防ぎます

2)クラスが継承されることを意図している場合、プライベート基本クラスデストラクタは許可されません(コンパイルエラーがスローされます)が、保護された基本クラスデストラクタは継承を許可します

3)保護された仮想デストラクタの継承のタイプ(パブリックおよび保護)により、マルチレベルの継承A-> B-> Cの安全な方法が可能になり、Cのデストラクタが呼び出されたときに、メモリがより適切にクリーンアップされます。

4)メモリがnewを使用して動的に割り当てられる場合、プライベートデストラクタだけでは削除を許可できません(auto_ptrについてはわかりませんが、「プライベート」デストラクタを使用するのと同じ考えに従う必要があると思います)。

特に、そのような実装に気付いていない人がそのようなクラスを使用しようとしている場合は、プライベートデストラクタを使用するとエラーが発生しやすくなる可能性があります。

保護されたパブリックデストラクタはいつでも歓迎され、使用法は上記のニーズによって異なります。

これが明らかになることを願っています。

于 2013-03-20T10:42:47.990 に答える
0

ここには2つの別個のルールが含まれます。まず、設計でベースへのポインタを介して派生型のオブジェクトを削除する必要がある場合、ベースのデストラクタは仮想である必要があります。第2に、メンバー関数(およびそれによってデストラクタを広く含む)が保護またはプライベートである場合、それを呼び出すことができるコンテキストは、パブリックの場合よりも制限されます(もちろん、デストラクタがプライベートの場合は、 tはクラスから派生します)。例えば:

class C {
protected:
    virtual ~C();
    friend void destroy_me(C*);
};

void destroy_me(C *cp) {
    delete cp; // OK: destructor is accessible
}

void destroy_someone_else(C *cp) {
    delete cp; // Error: destructor is not accessible
}
于 2013-03-20T11:15:44.110 に答える