【发布时间】:2014-03-05 10:13:03
【问题描述】:
我发现The rule of Zero 也提到了Peter Sommerlads Slides (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 调用正确的析构函数。如果我完全省略析构函数定义,它不会变为虚拟,因此会调用错误的 d'tor 是否正确?
struct Base {
virtual void drawYourself();
// no virtual destructor!
};
这引出了我的最后一个问题:
- “零规则”在具有虚拟方法的层次结构中是否也适用
- 或者在这些情况下我需要定义虚拟析构函数吗?
编辑:正如我在回答中被提醒的那样,我的 1sr 版本的问题有错误的假设。相关的(虚拟)析构函数位于Base,而不是Derived。但我的问题仍然存在:我是否需要声明(虚拟)析构函数?
【问题讨论】:
-
1) 当然。 2)当你认为你要多态地
delete时,你需要定义一个虚拟析构函数。 -
该死的。我发现“零规则”非常引人注目,因为如果应用得当,到目前为止它没有例外(与 C++ 中的所有其他内容不同)。现在这个希望消失了...... ;-)
-
= defaulting 特殊会员不以任何方式违反 Ro0。重要的部分是,您不必自己实现它们的功能,而是从处理单一职责的unique_ptr和vector等构建块派生它。 tbh,即使你有它,没有= default,对于析构函数来说也很好——因为你不需要手动在其中做任何事情。一切仍由相应成员的析构函数处理。 -
值得注意的是
std::shared_ptr<Base>,如果从Derived*(或make_shared<Derived>)构造,将通过调用Derived::~Derived()进行清理,并且不需要Base::~Base()是虚拟的。跨度> -
@towi:
std::shared_ptr是正确的。在std::unique_ptr中,您不会得到这种行为,因为自定义删除器是类型的一部分(即所有std::unique_ptr<Base, ThisDeleterType>都会以相同的方式删除对象)。所以unique_ptr自定义删除器确实对多态性没有用处。
标签: c++ c++11 destructor virtual-destructor rule-of-zero