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

时间:2014-02-07 20:33:52

标签: c++ c++11 destructor virtual-destructor rule-of-zero

我发现The rule of Zero(第32页)中提到的Peter Sommerlads Slides非常引人注目。

虽然,我似乎记得有一个严格的规则,一个来定义析构函数虚拟如果该类有< strong>虚拟成员,实际上是派生的。

struct Base {
    virtual void drawYourself();
    virtual ~Base() {}
};
struct Derived : public Base {
    virtual void drawYourself();
};

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

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

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

然后delete obj 调用正确的析构函数非常重要。这是否正确,如果我完全忽略析构函数定义它将不成为虚拟,因此会调用错误的数字?

struct Base {
    virtual void drawYourself();
    // no virtual destructor!
};

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

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

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

1 个答案:

答案 0 :(得分:6)

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

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

struct Derived : public Base {
    virtual void drawYourself();
};

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

如果按照这样做的方式执行,或者如果省略virtual析构函数,则只需通过基指针delete派生对象时获得未定义的行为。