"零规则"是否也适用于具有虚拟方法的类?

tow*_*owi 9 c++ destructor virtual-destructor c++11 rule-of-zero

我发现Peter Sommerlads Slides(第32页)中提到的零法则非常引人注目.

虽然,我好像记得,有一个严格的规则,一个定义虚拟析构函数,如果类有虚拟成员和实际的.

struct Base {
    virtual void drawYourself();
    virtual ~Base() {}
};
struct Derived : public Base {
    virtual void drawYourself();
};
Run Code Online (Sandbox Code Playgroud)

析构函数的主体甚至可能是空的(它只需要vtbl中的条目).

我似乎记得在使用层次结构时

int main() {
    Base *obj = new Derived{};
    obj->drawYourself(); // virtual call to Derived::drawYourself()
    delete obj; // Derived::~Derived() _must_ be called
}
Run Code Online (Sandbox Code Playgroud)

那么delete obj 调用正确的析构函数是很重要的.这是正确的,如果我完全省略了析构函数定义,它就不会变成虚拟的,因此会调用错误的数字吗?

struct Base {
    virtual void drawYourself();
    // no virtual destructor!
};
Run Code Online (Sandbox Code Playgroud)

这引出了我的最后一个问题:

  • 在使用虚方法的层次结构中,"零规则"也是如此
  • 或者我是否需要在这些情况下定义虚拟析构函数?

编辑:当我在答案中提醒时,我的问题的1sr版本有错误的假设.相关(虚拟)析构函数Base不在Derived.但我的问题是:我是否需要声明(虚拟)析构函数?

use*_*411 7

它实际上是必须声明为虚拟的基础析构函数,并且它在派生类中自动虚拟:

struct Base {
    virtual void drawYourself();
    virtual ~Base() = default;
};

struct Derived : public Base {
    virtual void drawYourself();
};
Run Code Online (Sandbox Code Playgroud)

但除此之外,零的规则仍然存在.

如果按照它的方式执行,或者如果省略virtual析构函数,则只需delete通过基指针获取派生对象时就会出现未定义的行为.

  • 您可能希望将"构造函数"更改为"析构函数" (3认同)