class Base
{
virtual void foo() = 0;
//~Base(); <-- No destructor!
};
明らかに、Base
派生します。では、C++ は、コンパイラによって生成されたデストラクタBase
が仮想でなければならないと言っていますか?
ありがとう!
class Base
{
virtual void foo() = 0;
//~Base(); <-- No destructor!
};
明らかに、Base
派生します。では、C++ は、コンパイラによって生成されたデストラクタBase
が仮想でなければならないと言っていますか?
ありがとう!
virtual
いいえ、そのようにマークしない限り、デストラクタは存在しません。理由は単純です。呼び出しは、ポインターと参照の両方を介して仮想的に行うことができ、仮想的に呼び出しを行う方法とかどうかは、を使用してオブジェクトを作成するかどうかとは無関係ですnew
。オブジェクトを作成しない場合は、オブジェクトを作成する必要がないため、仮想デストラクタは必要ありnew
ませdelete
ん。
そうではありません。これは、デストラクタが自動的に仮想化されないことの証明に近いです。
#include <iostream>
struct BaseBase {
~BaseBase() {
std::cout << "~BaseBase\n";
}
};
struct Base : BaseBase
{
virtual void foo() = 0;
//~Base(); <-- No destructor!
};
struct Derived : Base {
void foo() { std::cout << "foo\n"; }
~Derived() {
std::cout << "~Derived\n";
}
};
int main() {
Base *p = new Derived();
delete p;
}
このプログラムは実際には未定義の動作をしますが、あなたの実装では "~Derived" が出力されないのではないかと強く疑っています。仮想デストラクタがある場合Base
、未定義の動作はなく、「~Derived」と出力されます。
もちろん、実際には標準について何も証明していません。それを実行する実装は、結局のところ非準拠である可能性があります。しかし、いくつか試してみると、標準が何を言おうと、仮想デストラクタを指定する必要があることがわかります。
クラスは仮想メンバーを持つことができ、派生することができ、仮想デストラクタがなくても割り当てnew
および削除することさえできます。delete
違法 (UB) とは、デストラクタが仮想として宣言されていない場合に、delete
ベースへのポインタを使用して派生インスタンスを破棄することです。
もちろん、クラスが派生することを意図している場合、仮想デストラクタを宣言しない理由はまったくありません。
いいえ、dtor が仮想であることは保証されていません。
派生するように特別に設計されたクラスを宣言するときは、仮想 dtor を明示的に宣言することをお勧めします。通常、そうしないのは完全な設計上の欠陥です。実際、基本クラスから仮想 dtor を省略することが設計上の欠陥ではないケースは考えられません。