C++析构函数作为虚函数?

发布于 2024-11-16 11:11:24 字数 345 浏览 3 评论 0原文

我最近刚刚读到,将 C++ 析构函数实现为虚函数是一个很好的实践[1]。为什么会这样呢?这是一个普遍的良好做法吗?如果不是,在什么条件/情况下析构函数可以成为虚函数?

参考

  1. https://www.blackhat.com/presentations/bh-usa-07/Afek/Whitepaper/bh-usa-07-afek-WP.pdf

I just read recently that its a good practice to implement C++ destructors as virtual functions[1]. Why is this so? Is this a general good practice? If not, in what conditions/cases is a destructor to be made a virtual function?

Reference

  1. https://www.blackhat.com/presentations/bh-usa-07/Afek/Whitepaper/bh-usa-07-afek-WP.pdf

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

岁月静好 2024-11-23 11:11:24

Herb Sutter 在他的文章“虚拟性”中详细讨论了这个主题。指南 #4 指出“基类析构函数应该是公共的和虚拟的,或者是受保护的和非虚拟的。”

如果您的类不是设计或打算用作基类,那么没有理由使用虚拟析构函数来声明它。

Herb Sutter discusses this subject in great detail in his article "Virtuality." Guideline #4 states "A base class destructor should be either public and virtual, or protected and nonvirtual."

If your class isn't designed or intended to be used as a base class then there is no reason to declare it with a virtual destructor.

鹤仙姿 2024-11-23 11:11:24

如果基类有析构函数并且它不是虚拟的,那么在基类的指针上调用delete时,将不会调用任何子类的析构函数。

这可能会导致内存泄漏。

class Shape
{
public:
    Shape()
    {
        cout << "Shape constructor called" << endl;
    }
    // This destructor should be virtual!
    ~Shape()
    {
        cout << "~Shape destructor called" << endl;
    }
};

class Triangle : public Shape
{
public:
    Triangle()
    {
        cout << "Triangle constructor called" << endl;
    }
     ~Triangle()
    {
        cout << "Triangle destructor called" << endl;
    }

}

int main(int argc, char* argv[])
{
     Shape* pShape = new Triangle();
     cout << "About to call delete" << endl;
     delete pShape;
}

这将导致:

调用三角形构造函数
称为形状构造函数
即将调用删除
形状析构函数称为

任何应该在三角形析构函数中释放的资源现在都已泄漏。

If a base class has a destructor and it is NOT virtual, then any child class's destructor will not be called if delete is invoked on the base class's pointer.

This can result in memory leaks.

class Shape
{
public:
    Shape()
    {
        cout << "Shape constructor called" << endl;
    }
    // This destructor should be virtual!
    ~Shape()
    {
        cout << "~Shape destructor called" << endl;
    }
};

class Triangle : public Shape
{
public:
    Triangle()
    {
        cout << "Triangle constructor called" << endl;
    }
     ~Triangle()
    {
        cout << "Triangle destructor called" << endl;
    }

}

int main(int argc, char* argv[])
{
     Shape* pShape = new Triangle();
     cout << "About to call delete" << endl;
     delete pShape;
}

This will result in:

Triangle constructor called
Shape constructor called
About to call delete
Shape destructor called

Any resources that should be deallocated in the triangles destructor has now leaked.

回眸一笑 2024-11-23 11:11:24

来自 Scott Meyers 的《Effective C++》——“为基类提供虚拟析构函数的规则仅适用于多态基类 - 旨在允许通过基类接口操作派生类类型的基类。”

如果基类中有任何虚函数,则很可能必须将基类析构函数设为虚函数。

未设计为基类或未设计为多态使用的类不应声明虚拟析构函数

From Effective C++ by Scott Meyers - "The rule for giving base classes virtual destructors applies only to polymorphic base classes — to base classes designed to allow the manipulation of derived class types through base class interfaces."

It is most likely that if you have any virtual functions in your base class then the base class destructor must be made virtual.

Classes not designed to be base classes or not designed to be used polymorphically should not declare virtual destructors

眼泪都笑了 2024-11-23 11:11:24

当您的类具有虚拟析构函数时,您可以确保派生类中的析构函数将被调用。

When your class has a virtual destructor, then you ensure that destructors in derived classes will be called.

活雷疯 2024-11-23 11:11:24

可以说,如果您的整个类层次结构都是 POD 或析构函数没有什么可做的,那么您可能会因为没有虚拟析构函数而逃脱惩罚。但是,一旦您想从您的类派生其他类并且希望通过指针/基类引用多态地使用它们,您无论如何都会拥有虚函数,因此添加虚函数的开销很小虚拟析构函数,你永远不知道谁会继承你。一旦任何派生类需要一个不平凡的析构函数并且可以通过指向基类的指针引用,您必须有一个虚拟的析构函数。

经验法则:如果有任何虚拟函数,请添加虚拟析构函数。

(这里的要点是,如果您没有虚函数,那么就无法多态地使用派生类,因此需要非平凡破坏的非法子类不太可能通过基类指针删除仍然可以完成,只是可能性较小。)

Arguably if your entire class hierarchy is POD or has nothing for the destructors to do, you might get away with not having a virtual destructor. However, as soon as you want to derive other classes from your class and want to use them polymorphically through pointer/reference-to-base, you will have virtual functions anyway, so there is little overhead adding a virtual destructor, and you never know who will be inheriting from you. As soon as any derived class requires a non-trivial destructor and may be refered to via pointer-to-base, you must have a virtual destructor.

Rule of thumb: if you have any virtual functions, add a virtual destructor.

(The point here is that if you have no virtual functions, then there will be no way to use derived classes polymorphically, so it will be less likely that an illegitimate child class that requires non-trivial destruction will be deleted via a base class pointer. It could still be done, it's just less likely.)

闻呓 2024-11-23 11:11:24

http://blogs.msdn.com/b/oldnewthing /archive/2004/05/07/127826.aspx

在当今时代,我认为您应该将所有方法虚拟化,然后考虑哪些方法不需要 是。

好的,是的,我已经用 Java 完成了大部分 OOP。

http://blogs.msdn.com/b/oldnewthing/archive/2004/05/07/127826.aspx

In this day and age, I think you should make all methods virtual and then think which ones do not need to be.

OK, yeah, I've done most of my OOP in Java.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文