4

仮想デストラクタを理解しようとしています。以下は、このページからのコピペです。いつ仮想デストラクタを使用しますか?

ここで、Base のデストラクタが仮想であることを宣言していないことに気付くでしょう。それでは、次のスニペットを見てみましょう。

Base *b = new Derived(); // use b 
delete b; // Here's the problem!

[...] 基本クラス ポインターを介してインスタンスが削除されないようにする場合は、基本クラスのデストラクタを保護された非仮想にすることができます。そうすることで、コンパイラは基本クラス ポインターで delete を呼び出せなくなります。

保護された非仮想基本クラスのデストラクタを使用することで削除が防止される理由がわかりません。deleteコンパイラは、基本クラスのオブジェクトから呼び出そうとしていると考えていませんか? それと何の関係がprotectedありますか?

4

3 に答える 3

11

C++ 標準には、次のように書かれていますdelete(セクション 5.3.5p10):

アクセスとあいまいさの制御は、解放関数とデストラクタの両方に対して行われます (12.4、12.5)。

したがって、デストラクタにアクセスできるコードのみが を使用できますdelete。デストラクタがであるため、誰もタイプ のポインタをprotected呼び出すことができないことを意味します。サブクラスのみがデストラクタをまったく使用できます (サブオブジェクトの破棄プロセスの一部として、サブクラス自体のデストラクタのみが使用されます)。deleteBase*

もちろん、サブクラスは独自の destructor を作成しpublic、サブクラスの型を介してオブジェクトを削除できるようにする必要があります (それが正しい実際の型であると仮定します)。

注: 実際には、 の他のメンバーはアクセス権を持っているためBase実行できdelete (Base*)p;ます。しかし、C++ は、この構造を使用する人がそれを行わないことを想定しています。C++ アクセス制御は、クラス外のコードへのガイダンスを提供するだけです。

于 2013-10-25T01:12:36.307 に答える
6

delete b;効果的に行いb->~Base(); deallocate(b);ます。最初の部分 (デストラクタの呼び出し) は、デストラクタにアクセスできない場合 (他のアクセスできないメソッドの呼び出しが失敗するのと同じ方法で) コンパイルに失敗します。

于 2013-10-25T01:12:10.833 に答える