每个class级都应该有一个虚拟的析构函数吗?

Java和C#支持不能用作具有final sealed关键字的基类的类的概念。 然而,在C ++中,没有什么好方法可以防止从类派生出类,如果每个类都有一个虚拟析构函数,那么这个类的作者就会左右为难。


编辑:由于C ++ 11这不再是真实的,你可以指定一个类是final


一方面给一个对象一个虚拟的析构函数意味着它将有一个vtable ,因此每个对象为vptr消耗4个(或64位机器上的8个)附加字节。

另一方面,如果稍后有人从这个类派生出来并通过一个指向基类的指针删除一个派生类,那么程序将会是不明确的(由于没有虚拟析构函数),并且坦率地说,对每个对象的指针进行优化是荒谬。

在具有虚拟析构函数的抓手上(可以说)宣称这种types意图被多态使用。

有些人认为你需要一个明确的理由不使用虚拟析构函数(就像这个问题的潜台词),而另外一些人则说,只有当你有理由相信你的类是派生出来的时候,你才应该使用它们, 认为?

问题是,你是否想强制执行关于你的类应该如何使用的规则? 为什么? 如果一个类没有虚拟析构函数,那么使用这个类的任何人都知道它不是来源于这个类的,而且如果你尝试使用它,又有什么限制。 这不够好吗?

或者如果有人敢做一些你没有预料到的事情,你是否需要编译器发出一个严重的错误?

如果你打算让人从中派生出来的话,给这个类一个虚拟的析构函数。 否则不要,并假设使用你的代码的人都足够聪明,正确使用你的代码。

每个抽象类都应该有一个,

  • 受保护的析构函数,或者,
  • 虚拟析构函数。

如果你有一个公共的非虚拟析构函数,那就不好了,因为它允许用户通过该指针删除一个派生对象。 因为我们都知道,这是未定义的行为。

对于不想通过指向它的指针删除的类,没有任何理由拥有虚拟析构函数。 这不仅会浪费资源,更重要的是会给用户一个错误的提示。 只要想一想, std::iterator是一个虚拟析构函数会有多糟糕的感觉。

没有! 仅当通过基类指针删除派生类的对象时才使用虚拟析构函数。 如果你的类不打算作为这种情况下的基础,不要使析构函数虚拟 – 你会发送一个错误的信息。

从Herb Sutter检查这篇文章 :

准则4:基类析构函数应该是public和virtual,或者是protected和nonvirtual。

我会对一般问题“不”。 不是每个class都需要一个class。 如果你知道class级永远不能inheritance,那么就没有必要承担小小的开销。 但是如果有机会的话,就放在安全的一边,把它放在那里。

我会补充一点,有些时候,当我在父母或孩子class上忘记了一个虚拟的东西的时候,我已经把我的脑袋划伤了一段时间了。 我想现在我知道了。 🙂

有人可能会争辩说,父类有时会在其析构函数中做一些小孩不应该做的事情……但是这可能反映了你的inheritance结构有问题。

当基类包含至less一个纯虚函数时,它就成为抽象类。 如果Base不具有虚拟析构函数,并且Derived(派生自Base),那么可以通过Derived对象指针安全地销毁Derived对象,但不能通过Base对象指针。

 include<iostream> using namespace std; class base { public: base() { cout << "In base class constructor" << endl; } virtual ~base() { cout << "in base class destuctor" << endl; } }; class derived : public base { public: derived() { cout << "in derived class constructor" << endl; } ~derived() { cout << "in derived class destructor" << endl; } }; int main() { base *b; // pointer to the base class b = new derived; // creating the derived class object using new keyword; delete b; return 0; }