多层继承中的虚拟关键字

时间:2018-07-26 08:03:47

标签: c++ polymorphism

我有一个继承链,其中A类从B类公开继承,而B类又从C类公开继承。C类的析构函数被标记为“虚拟”。是否有反对将B和A类的析构函数标记为虚拟的反对意见?还是在这种情况下需要支付性能/内存罚款?

2 个答案:

答案 0 :(得分:6)

如果将基类析构函数标记为虚拟,则派生类析构函数也将隐式虚拟化,则无需将其明确指定为虚拟。 没有性能或记忆力上的损失

因此,在您的示例中,如果C具有虚拟析构函数B并且A继承了析构函数的“虚拟性”

答案 1 :(得分:3)

是的,有。一旦存在至少一个虚拟成员函数(特殊或普通),编译器便会为这种层次结构创建并管理一个vtable。

但是,由于以下情况是前往UB的路线

designTime

将上述基类更改为

是一种常见的自动操作
class Base {};

class Derived : public Base {};

Base *b = new Derived{};

delete b; /* Undefined behavior, destructor of B is not virtual. */

,现在可以通过class Base { public: virtual ~Base() = default; }; 虚拟析构函数安全地删除任何派生类。

在某些情况下,继承层次结构应该扩展类功能,而无需用例引用基本实例。然后,应使用受保护的非虚拟析构函数。因此,只能从派生类中销毁基类:

B

不允许使用此代码段

class Base {
  protected:
    ~Base() = default;
};

但允许

Base *b = new Derived{};

delete b; /* Error, ~Base() is protected. */

并因此避免了类使用的不确定性,同时编译器不会为您生成vtable,从而实现最佳性能。这是一种常见的技术,例如在基于策略的设计中。