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

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

谢谢!

4

4 回答 4

7

不,virtual除非您将其标记为析构函数,否则析构函数不会。原因很简单 - 可以通过指针和引用进行虚拟调用,以及如何以及是否进行虚拟调用与是否使用new. 如果你不创建对象,new你就不需要delete它们,所以你不需要虚拟析构函数。

于 2011-08-12T14:56:07.947 回答
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”。

当然,它实际上并不能证明该标准的任何内容。您运行它的任何实现都可能不符合标准。但是一旦你尝试了一些,你就会明白无论标准怎么说,你都需要指定一个虚拟析构函数。

于 2011-08-12T15:01:23.630 回答
1

不,不保证 dtor 是虚拟的。

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

于 2011-08-12T14:58:02.473 回答
1

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

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

当然,如果您的类是要派生的,那么根本没有理由不声明虚拟析构函数。

于 2011-08-12T15:10:20.420 回答