12

我发现Peter Sommerlads 幻灯片(p.32)中也提到的零规则非常引人注目。

虽然,我似乎记得有一个严格的规则,即必须定义析构函数 virtual如果该类具有虚拟成员并且实际上是派生的。

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 调用正确的析构函数很重要。是否正确,如果我完全省略了析构函数定义,它就不会变成 virtual,因此会调用错误的 d'tor 吗?

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

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

  • “零规则”在具有虚拟方法的层次结构中是否也适用
  • 还是在这些情况下我需要定义虚拟析构函数?

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

4

1 回答 1

8

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

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

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

但除此之外,零规则仍然有效。

如果您按照您的方式进行操作,或者如果您省略了virtual析构函数,那么在delete通过基指针 ing 派生对象时,您只会得到未定义的行为。

于 2014-02-07T20:35:27.640 回答