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

C++ 是不是;“零规则”;是否也适用于具有虚拟方法的类?,c++,c++11,destructor,virtual-destructor,rule-of-zero,C++,C++11,Destructor,Virtual Destructor,Rule Of Zero,我发现(第32页)也提到了这一点,这一点非常引人注目 尽管如此,我似乎记得有一条严格的规则,必须定义析构函数virtual,如果类具有虚拟成员,并且实际上是派生的 struct Base { virtual void drawYourself(); virtual ~Base() {} }; struct Derived : public Base { virtual void drawYourself(); }; 析构函数的主体甚至可能是空的(它只需要vtbl中的条目

我发现(第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
调用正确的析构函数。如果我完全忽略了析构函数的定义,它不会变成虚拟的,因此会调用错误的d'tor,这是正确的吗

struct Base {
    virtual void drawYourself();
    // no virtual destructor!
};
这就引出了我的最后一个问题:

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

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

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

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

struct Derived : public Base {
    virtual void drawYourself();
};
但除此之外,零原则仍然适用


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

愚蠢的我。让我们修正我的问题。你可能想将“构造函数”改为“析构函数”,而不是“除此之外”-这仍然属于Ro0,并且
=default
@Xeo是的,也许是,但你仍然必须记住它。然后在它前面写
virtual
。并且仅适用于具有另一个虚拟方法的类。如果没有派生类(实际上,这是毫无意义的),则可以使用它。不管怎样,我们仍然需要解释原因。1)当然。2) 当您认为要以多态方式删除时,需要定义一个虚拟析构函数。我发现“零规则”非常有说服力,因为如果应用正确,到目前为止它没有任何例外(与C++中的所有其他规则不同)。现在这个希望已经破灭了…;-)<代码>=默认值ing特殊成员不会以任何方式违反Ro0。重要的一点是,您不需要自己实现它们的功能,而是从诸如
unique\u ptr
vector
之类的构建块中派生出来,这些构建块处理单个责任。tbh,即使您拥有它,如果没有
=default
,对于析构函数来说也很好——因为您不需要在其中手动执行任何操作。所有内容仍由相应成员的析构函数处理。值得注意的是,
std::shared_ptr
,如果由
Derived*
(或
make_shared
)构造,将通过调用
Derived::~Derived()
进行清理,并且不需要
Base::~Base()
是虚拟的。@towi:std::shared\u ptr就是这样。在
std::unique_ptr
中,您不会得到该行为,因为自定义删除器是该类型的一部分(即所有
std::unique_ptr
将以相同的方式删除对象)。因此,
unique\u ptr
自定义删除程序对于多态性来说确实没有用处。