我'阅读了一些文章,正如他们所说,主要的虚拟析构函数用例是:
派生的类可以从堆中进行动态数据分配,即"拥有"那个数据对象。因此,他们需要在析构函数中使用一些删除例程。通过 base 类指针删除需要在所有派生类中声明析构函数,直到那些具有动态数据分配( base 类也需要它)
此类有virtual
个方法。但这对我来说还不清楚。只需通过 base 类指针调用virtual
方法,就会产生最多派生的 - 实现调用。他们只对该规则的排除是建设阶段。 Literaly,在它virtual
期间,对象不是派生的类型,即使以后也是如此。好的,破坏阶段呢?据我所知,规则是向后的顺序。无论如何,层次结构中某个类的析构函数声明为this
,在每个析构函数virtual
指针中使用该类类型时,由于this
dr,任何派生都已被销毁,或者没有销毁(假设某些设计可能没问题)。也许就是这种情况,为什么d-r必须是虚拟的? Vtable将包含派生类的条目,并且从d-r调用某些 base 类中的virtual
方法将导致UB?好的,但是此规则仅适用于此类在d-r中调用某些virtual
方法的情况,并且它们确实在派生类中实现。
我的观点是,也可能存在没有动态数据分配的情况,所有层次结构中都没有虚拟方法,但仍然派生的析构函数可能会在删除(同步,解锁等)时执行一些关键任务。我们需要基类中的虚拟d-r。可能是这种情况是糟糕设计的结果。
但无论如何,一些公共类的开发人员不能100%知道,如果派生类会在d-r中使用某些虚方法,还是分配动态数据。那么,我是否正确地说,任何未声明为virtual
的公共类必须将d-r声明为虚拟?只有final
关键字才能保证指向此类的任何指针始终属于此类型,因此可以非虚拟地安全删除。
答案 0 :(得分:3)
如果通过指向基类的指针删除派生对象,那么(并且只有这样)基类析构函数必须是虚拟的。否则为undefined behaviour。没有其他相关规则。
如果该类具有虚函数,则不会引入任何开销。如果类没有任何其他虚函数,则基类设计者必须考虑添加虚拟析构函数的运行时惩罚与该类用户可能尝试通过以下方法删除派生对象的风险之间的交易。基类指针。
Here is a link to a similar discussion, with Standard quotes