考虑一个情形:当我们用基类指针指向派生类对象,然后通过基类指针删除派生类对象时,如果基类的析构函数不是虚函数,那么只会调用基类的析构函数,而不会调用派生类的析构函数,导致内存泄漏或资源未正确释放
藉此引出了一个问题,即“我们应不应该让所有的析构函数都是虚函数”以规避上述情形的发生。
由于虚函数需要虚函数表来维护,假设我们这样做,则会导致向类的每个实例添加一个额外的虚指针,这样会导致性能损失。
避免使用虚析构函数的情形
所以我们首先应当考虑可以避免使用虚函数和虚析构函数的情况有哪些?
答案是:如果一个类不是用来作为基类(即不打算被继承),那么就不应该使用虚函数,也不需要虚析构函数。
那么接下来的问题就是,如果决定让一个类不可继承,那么是否有可能强制使得这个情形发生。
答案是:如果您不打算让您的类被继承,那么请将您的类标记为 final 类型。这样做首先就能阻止其他类对其进行继承,同时也不会对这个类本身施加任何其他使用限制。
原因是:虚函数表(vtable)会增加额外的内存和运行时开销,而这些开销在不需要多态的情况下是不必要的。
需要使用虚析构函数的情形
如果说,虽然我不打算将一个类设置为基类或者说我不打算它被继承,但是我又想其他类能够使用他,即没有继承的情况下复用类。我应该怎么做呢?
答案是:这个类仍然可以通过组合(composition)的方式被其他类使用。组合是一种has-a或者part-of的关系,而继承则是is-a的关系。比如说,我们可以在另一个类中包含该类的对象,而不是让新类从它继承。
分析玩可以避免使用虚析构函数的情况,我们来考虑那些不得不使用虚析构函数的情况有哪些。
答案是:如果一个类被设计为基类,或者说它有任何虚函数,那么它应该始终拥有一个虚析构函数。其原因就是为了规避我们开头提到的那种情况的发生。