デストラクタを仮想関数として宣言する必要があるかどうか

派生クラスが基本クラスを継承し、派生クラスオブジェクトへの基本クラスポインターがある場合、デストラクターは仮想関数として宣言する必要があります。

デストラクタが仮想関数ではなく、派生クラスオブジェクトの基本クラスへのポインタである場合、オブジェクトが破棄されると、派生クラスのデストラクタの代わりに基本クラスのコンストラクタが呼び出され、メモリリークが発生する可能性があります。
なぜこれが基本クラスのコンストラクタを呼び出すのですか?デストラクタが仮想関数でない場合、デストラチャ中に実際に呼び出される関数は、コンパイル時にポインタ型クラスのデストラクタ、つまり基本クラスのデストラクタとして決定されるためです。

たとえば、デストラクタは仮想関数であり、派生クラスオブジェクトの基本クラスへのポインタです。オブジェクトが破棄されると、派生クラスのデストラクタが呼び出され、派生クラスのデストラクタが自動的に基本クラスのデストラクタを呼び出します。これにより、メモリーリーク。
なぜこれが派生クラスのコンストラクタを呼び出すのですか?仮想関数のデストラクタとして宣言されているため、構造化中に実際に実行される関数のアドレスはコンパイル時に不確定になります。実行時に、実際に構造化中に実行される関数は、仮想テーブルポインタと仮想関数テーブルに基づいて計算されます。アドレス、つまり、派生クラスのデストラクタのアドレス。
派生クラスのデストラクタのアドレスがこのように計算されるのはなぜですか?仮想テーブルポインターはすべての派生クラスオブジェクトによって所有され、派生クラスの仮想関数テーブルを指すため、派生クラスの仮想関数テーブルには、仮想関数として宣言されたデストラクターのアドレスが格納されます。

クラスのすべてのデストラクタを仮想関数として宣言する必要があるのは本当ですか?いいえ、クラスが派生クラスを持たない場合、またはクラスが基本クラスであり、派生クラスを持っているが、基本クラスポインターが派生クラスオブジェクトを指している場合、このクラスのデストラクターを仮想として宣言する必要はありません。関数。これが仮想関数として宣言されている場合は、構造化解除中に仮想関数テーブルをチェックするプロセスが増え、メモリ内に保持する仮想関数テーブルと仮想テーブルポインターが増えるため、オーバーヘッドが増加します。

おすすめ

転載: blog.csdn.net/wx_assa/article/details/107844125