构造函数不能是虚拟的。
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()
是一个指向圆的指针。将此类型分配给指向 Shape 类型指针的变量涉及隐式转换。转换的结果是指向 Circle 的基本 Shape 子对象的指针。同样,这一切都不是虚拟的,因为 Shape 不是虚拟基础,它只是一个常规基础对象,并且它在 Circle 内的位置是静态已知的。
delete s
确实调用了 Circle 析构函数。这确实使用了虚拟调度。编译器知道它正在删除一个 Shape,并且 Shape 的析构函数是虚拟的,因此它会查找适当的析构函数 is~Circle()
并调用它。如果 Shape 的析构函数不是虚拟的(并且实际上在某处有定义),则不会这样做,只有 Shape 对象会被破坏,而不是 Circle 对象,并且释放可能无法正确完成。行为将是未定义的。