質問するログイン新規登録

回答編集履歴

1

文献追加

2018/08/17 10:50

投稿

raccy
raccy

スコア21807

answer CHANGED
@@ -1,4 +1,12 @@
1
1
  Stack Overflowに同様の質問がありました。
2
2
  [c++ - virtual destructor fail using array - Stack Overflow](https://stackoverflow.com/questions/7754532/virtual-destructor-fail-using-array)
3
3
 
4
- どうやら、new[]で作る配列の場合、多態性があるものとして扱われないようです。つまり、virtualがついていようが静的な型(コンパイル時に決定される変数自体の型)であるBaseとして扱って、動的な型(実行時に判別されるオブジェクト自体の型)であるDerivedとしては扱わないということらしいです。このように静的な型と動的な型が一致せず、virtualなデストラクタになっている場合は、**未定義な動作**となるとのことです。未定義な動作ですので、Baseのデストラクタだけが呼ばれる場合も、Derivedのデストラクタが呼ばれる場合も、もっと言えばエラーで落ちてしまっても、C++としては仕様通りの動作となります。
4
+ どうやら、new[]で作る配列の場合、多態性があるものとして扱われないようです。つまり、virtualがついていようが静的な型(コンパイル時に決定される変数自体の型)であるBaseとして扱って、動的な型(実行時に判別されるオブジェクト自体の型)であるDerivedとしては扱わないということらしいです。このように静的な型と動的な型が一致せず、virtualなデストラクタになっている場合は、**未定義な動作**となるとのことです。未定義な動作ですので、Baseのデストラクタだけが呼ばれる場合も、Derivedのデストラクタが呼ばれる場合も、もっと言えばエラーで落ちてしまっても、C++としては仕様通りの動作となります。
5
+
6
+ ---
7
+ 日本語の文献も見つけたので紹介しておきます。
8
+ [operator delete, operator delete[] - cppreference.com](https://ja.cppreference.com/w/cpp/memory/new/operator_delete)
9
+ > #### クラス固有のオーバーロード
10
+ > ...
11
+ > 削除されるオブジェクトの静的な型がその動的な型と異なる場合 (基底へのポインタを通して多相オブジェクトを削除するときなど)、そしてその静的な型のデストラクタが virtual な場合、単一オブジェクト形式の delete はその仮想デストラクタの最終オーバーライダーの定義地点から解放関数の名前の探索を開始します。 実行時にどの解放関数が実行されるかにかかわらず、コンパイルするためには operator delete の静的に可視なバージョンがアクセス可能でなければなりません。 それ以外の場合では、**基底へのポインタを通して配列を削除するとき**、または非仮想デストラクタを持つ基底へのポインタを通してアクセスするとき、**動作は未定義です**。
12
+ > ...