コンストラクターを仮想にすることはできません。
class Shape {
virtual ~Shape() = 0;
};
class Circle : public Shape {
Circle() {};
~Circle() {};
};
int main() {
Shape *s = new Circle();
delete s;
}
はい、new Circle()
Circle のコンストラクターを呼び出します。これは、式がnew <type><optional initializer>
十分なメモリを割り当ててから、適切なコンストラクタ (または非クラス型のその他の初期化) を呼び出して初期化するためです。最も派生した型を明示的に述べているため、これについて仮想である必要はありません。
の結果はnew Circle()
Circle へのポインターです。この型を Shape へのポインター型の変数に割り当てるには、暗黙的な変換が必要です。変換の結果は、Circle の基本 Shape サブオブジェクトへのポインターです。Shape は仮想ベースではなく、通常のベース オブジェクトであり、Circle 内の位置は静的に知られているためです。
delete s
Circle デストラクタを呼び出します。これは仮想ディスパッチを使用します。コンパイラは、Shape を削除していることを認識しており、Shape のデストラクタは仮想であるため、適切なデストラクタ ( ) を検索して~Circle()
呼び出します。Shape のデストラクタが仮想的でない (実際にどこかに定義がある) 場合、これは行われず、Circle オブジェクトではなく Shape オブジェクトのみが破棄され、割り当て解除が正しく行われない可能性があります。動作は未定義です。