83

仮想デストラクタを備えた基本クラスがある場合。仮想デストラクタを宣言するための派生クラスもありますか?

class base {
public:
    virtual ~base () {}
};

class derived : base {
public:
    virtual ~derived () {} // 1)
    ~derived () {}  // 2)
};

具体的な質問:

  1. 1)と2)は同じですか?2)そのベースのために自動的に仮想化されますか、それとも仮想化を「停止」しますか?
  2. 派生したデストラクタは、関係がない場合は省略できますか?
  3. 派生デストラクタを宣言するためのベストプラクティスは何ですか?仮想、非仮想と宣言しますか、それとも可能であれば省略しますか?
4

5 に答える 5

98
  1. はい、同じです。派生クラスが仮想的なものを宣言していなくても、仮想化が妨げられることはありません。実際、メソッド(デストラクタを含む)が基本クラスで仮想である場合、派生クラスで仮想になるのを止める方法はありません。> = C ++ 11ではfinal、派生クラスでオーバーライドされないようにするために使用できますが、仮想化を防ぐことはできません。
  2. はい、派生クラスのデストラクタは、関係がない場合は省略できます。そして、その仮想かどうかは関係ありません。
  3. できれば省略します。また、わかりやすくするために、派生クラスでは常にvirtualキーワードまたは仮想関数のいずれかを使用しています。override関数が仮想であることを理解するために、継承階層をずっと上に行く必要はありません。さらに、クラスが独自のコピーまたは移動コンストラクターを宣言せずにコピー可能または移動可能である場合、任意の種類のデストラクタを宣言すると(として定義した場合でもdefault)、必要に応じてコピーおよび移動コンストラクターと割り当て演算子を宣言する必要があります。コンパイラーがそれらをあなたのためにもう入れないので、それら。

項目3の小さなポイントとして、コメントで、デストラクタが宣言されていない場合、コンパイラはデフォルトのデストラクタ(まだ仮想)を生成することが指摘されています。そして、そのデフォルトはインライン関数です。

インライン関数は、プログラムの他の部分の変更にプログラムの多くをさらす可能性があり、共有ライブラリのバイナリ互換性をトリッキーにします。また、結合の増加は、特定の種類の変更に直面して多くの再コンパイルをもたらす可能性があります。たとえば、仮想デストラクタの実装が本当に必要であると判断した場合は、それを呼び出したすべてのコードを再コンパイルする必要があります。一方、クラス本体で宣言してから.cppファイルで空に定義した場合は、再コンパイルせずに変更しても問題ありません。

私の個人的な選択は、可能であればそれを省略することです。私の意見では、コードが乱雑になり、コンパイラーは、空の実装よりもデフォルトの実装を使用すると、わずかに効率的な処理を実行できる場合があります。しかし、あなたが下にあるかもしれない制約があり、それはそれを悪い選択にします。

于 2010-02-04T09:04:13.927 に答える
2
  1. すべてのメソッドと同様に、デストラクタは自動的に仮想になります。メソッドが C++ で仮想であることを止めることはできません (すでに仮想として宣言されている場合、つまり、Java に「final」に相当するものがない場合)。
  2. はい、省略可能です。
  3. このクラスをサブクラス化する場合は、別のクラスをサブクラス化するかどうかに関係なく、仮想デストラクタを宣言します。必要がない場合でも、メソッドを仮想的に宣言し続けることを好みます。これにより、継承を削除することにした場合でも、サブクラスが機能し続けます。しかし、これは単にスタイルの問題だと思います。
于 2010-02-04T09:06:40.077 に答える
1

仮想メンバー関数は、この関数のオーバーロードを暗黙的に仮想にします。

したがって、1) の仮想は「オプション」です。基本クラスのデストラクタが仮想であると、すべての子デストラクタも仮想になります。

于 2010-02-04T09:04:25.287 に答える
0

1/はい 2/はい、コンパイラによって生成されます 3/仮想と宣言するかどうかの選択は、オーバーライドされた仮想メンバーの規則に従う必要があります-私見、両方の方法で適切な議論があります。

可能であれば省略しますが、それを宣言するように促す可能性のあることが 1 つあります。コンパイラで生成されたものを使用すると、暗黙的にインラインになります。インライン メンバ (動的ライブラリなど) を避けたい場合があります。

于 2010-02-04T09:07:55.010 に答える