web-dev-qa-db-ja.com

デフォルトのデストラクタを仮想デストラクタとして自動的に生成できますか?

デフォルトのデストラクタを仮想デストラクタとして自動的に生成できますか?

基本クラスを定義してもデフォルトのデストラクタを定義しない場合、デフォルトの仮想デストラクタは自動的に生成されますか?

52
user53670

いいえ。メソッドを仮想化することにはコストがかかります。C++には、使用したいことを明示的に述べていないものに対しては支払いを行わないという哲学があります。仮想デストラクタが自動的に生成されたとしたら、あなたは自動的に価格を支払っていたでしょう。

空の仮想デストラクタを定義しないのはなぜですか?

45
Uri

C++ 11では、以下を使用できます。

class MyClass
{
  // create a virtual, default destructor
  virtual ~MyClass() = default;
};
49
Drew Noakes

いいえ、すべてのデストラクタはデフォルトでは仮想ではありません。

すべての基本クラスで仮想デストラクタを定義する必要があります

それに加えて。

スコットマイヤーズの著書「Effective C++」で引用するには:

C++言語標準は、このトピックに関して非常に明確です。基本クラスポインターを介して派生クラスオブジェクトを削除しようとし、基本クラスに非仮想デストラクタがある場合(EnemyTargetと同様)、結果は未定義です

実際には、誰かが最終的にクラスから派生クラスを作成する可能性があると思われる場合は、通常、仮想デストラクタを使用してクラスを定義することをお勧めします。とにかく、すべてのクラスに仮想デストラクタを作成する傾向があります。はい、それに関連するコストがありますが、仮想化をあまり頻繁に行わないことによるコストは、実行時のオーバーヘッドのほんの少しの負担になります。

コンパイラーが実施するデフォルトの非仮想に依存するのではなく、そうしたいことが確実である場合にのみ、非仮想にすることをお勧めします。あなたは反対かもしれませんが、(要約すると)最近、いくつかのレガシーコードで恐ろしいメモリリークがあり、数年前から存在していたクラスの1つにstd :: vectorを追加するだけでした。基本クラスの1つにデストラクタが定義されていないことがわかり(デフォルトのデストラクタは空であり、非仮想です)、その時点までメモリがリークする前に、このようにメモリが割り当てられていなかったことがわかりました。何日もの調査と時間の浪費...

9
Matt

はい、仮想デストラクタを使用して基本クラスから継承します。この場合、ポリモーフィッククラス(vtableなど)の料金はすでに支払っています。

9
MSalters

UriとMichaelは正解です。デストラクタを宣言して定義するために2つのファイルを変更する必要がある場合は、ヘッダーにインラインを1つだけ定義しても問題ありません。

class MyClass
{
   // define basic destructor right here
   virtual ~MyClass(){}

   // but these functions can be defined in a different file
   void FuncA();
   int FuncB(int etc);
}
8
Crashworks

現在riが正しいです。一方、クラスで仮想メソッドを宣言した後は、いずれにしても仮想テーブルの存在に対する代償を払うことになります。実際、クラスに仮想メソッドはあるが仮想デストラクタがない場合、コンパイラは警告を出します。これは、厄介な警告ではなく、デフォルトの仮想デストラクタの自動生成の候補になる可能性があります。

2
Thinkeye

いいえ。仮想として宣言する必要があります。