0

この質問は、仮想デストラクタでの説明のように見えます。動的にメモリが割り当てられていない場合に必要ですか?

試験の質問で、私は尋ねられました:-動的に割り当てられたメモリへのポインタを維持する基本クラスは何を定義する必要がありますか?

私は答えました:-コピーコンストラクタと代入演算子(ポインタだけがコピーされるのではないことを確認するために...ディープコピーを参照)、およびデストラクタ(割り当てられたメモリを解放するため)

この基本クラスは、プレーンデストラクタではなく仮想デストラクタも定義する必要があるため、これは正しくないと彼らは言いました。なんで?

4

6 に答える 6

6

クラスがポリモーフィックに使用されることを意図している場合、派生オブジェクトを指す基本クラスへのポインターがある可能性があります。

デストラクタのない基本クラスへのポインタを介して派生オブジェクトを削除すると、virtual未定義の動作が発生します。それはおそらく彼女の推論です。

5.3.5

3) 最初の選択肢 (delete object ) で、オペランドの静的型がその動的型と異なる場合、静的型はオペランドの動的型の基本クラスであり、静的型は仮想デストラクタまたは動作を持たなければならない未定義です。[...]

于 2012-09-07T14:35:52.920 に答える
5

派生クラスのオブジェクトが基本クラスのポインターを介して破棄されることを意図している場合、基本クラスには仮想デストラクタが必要です。

Base *pointer_to_base_class = new Derived;
delete pointer_to_base_class;

あなたの質問からは、これが事実であるかどうかは不明です。おそらく、質問の別の部分 (または前の質問) で、そのようなポリモーフィックな破壊が意図されていることが明らかになりました。あるいは、そのような使用法をベスト プラクティスとして常に予測するように授業中に教えられたのかもしれません。

于 2012-09-07T14:36:26.233 に答える
5

それらは 100% 正しいわけではありません。仮想デストラクタは必須です

  1. 動的ポリモーフィズムで使用されるクラス階層 AND
  2. 派生オブジェクトは、ベースへのポインターを介して破棄されます。

それ以外の場合は、非仮想デストラクタで問題ありません。しかし、ほとんどの場合、#1 だけが意図されている場合でも、#2 に関係なくデストラクタを仮想化するのは良いスタイルです。

于 2012-09-07T14:41:15.107 に答える
1

標準内では、ほとんどの継承階層のベースに仮想デストラクタがあります。ただし、sub_matchpublic inherit from に定義されているため、std::pair<BidirectionalIterator, BidirectionalIterator>動的に割り当てられたメモリを所有できます。関連する領域では、必須ではありませんが、通常は確実にメモリを割り当てるmatch_resultspublic inherit に実装されます。std::vector<...>

あなたの審査官は完全に間違っているわけではありませんが、動的に割り当てられたメモリに焦点を当てることは赤ニシンであり、標準の懸念される無知を裏切っています。ほとんどの実装では、仮想デストラクタなしで基本型へのポインタによって派生型を削除すると、スライスされたオブジェクトが破棄されますが、標準では未定義の動作です。

于 2012-09-07T16:09:40.323 に答える
0

ここですべての良い答えをフォローアップするには、仮想デストラクタを宣言して、クラスがサブクラス化されて階層を形成することになっているときに、そのオブジェクトへのポインタを介して派生オブジェクトを削除する場合に、適切なクリーンアップを保証することをお勧めします。C ++標準はこれについて明確です:

基本クラスポインタを介して派生クラスオブジェクトを削除する必要があり、基本クラスのデストラクタが仮想ではなく、結果が未定義の場合

未定義の動作により、たとえば、派生クラスが動的メモリを割り当て、後でこの基本クラスを介してそれを削除しようとした場合に、メモリリークが発生する可能性があります。あなたの先生はおそらくこのシナリオを考えていました。

于 2012-09-07T14:59:13.340 に答える
0

他の回答への追加:共通の基本クラスが必要な状況を想定することもできますが、実際のインターフェイス関数はありません。しかし、RTTI と動的キャストのサポートが必要な場合は、クラスに仮想関数が必要です。デストラクタはまさにその機能です。

たとえば、あなたが回復中の Java プログラマーであり、すべてがObject. 次のように最初の C++ プログラムを開始できます。

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

Objectこれで、実際に各クラスの究極のポリモーフィック ベース クラスとして機能することができます。

Objectそれも抽象的であるべきだと思う場合は、デストラクタを純粋仮想にすることもできます。

class Object { public: virtual ~Object() = 0; }; Object::~Object() { }

于 2012-09-07T14:41:27.587 に答える