编译器生成的抽象基类的析构函数是虚拟的吗?

时间:2011-08-12 14:51:47

标签: c++ abstract-class destructor compiler-generated

class Base
{
    virtual void foo() = 0;
    //~Base();     <-- No destructor!
};

显然,Base将会派生出来。那么,C ++是否说编译器生成的Base析构函数必须是虚拟的?

谢谢!

4 个答案:

答案 0 :(得分:6)

不,析构函数不会是virtual,除非您将其标记为此类。原因很简单 - 几乎可以通过指针和引用进行调用,以及虚拟调用的方式和方式与是否使用new创建对象无关。如果您不使用new创建对象,则不必使用delete,因此您不需要虚拟析构函数。

答案 1 :(得分:2)

没有。这接近证明析构函数不会自动变为虚拟:

#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”。

当然,它实际上并没有证明标准。您运行它的任何实现都可能毕竟不符合要求。但是,一旦你尝试了几个,你就会明白无论标准如何,你都需要指定一个虚拟的析构函数。

答案 2 :(得分:1)

不,不保证dtor是虚拟的。

当声明专门设计为派生的类时,其明确声明虚拟dtor的良好做法。这通常是一个彻头彻尾的设计缺陷。事实上,我想不出一个设计缺陷就是从基类中省略虚拟dtor的情况。

答案 3 :(得分:1)

没有。一个类可以有虚拟成员,可以派生,甚至可以用new分配,并在没有虚拟析构函数的情况下用delete删除。

非法(UB)要做的是,如果析构函数未声明为虚拟,则使用指向base 的指针使用delete 销毁派生实例。

当然,没有理由不声明虚拟析构函数,如果你的类是派生的。