C ++'interfaces'应该有一个虚拟析构函数吗?

时间:2010-09-02 15:15:46

标签: c++

  

可能重复:
  Destructors for C++ Interface-like classes

考虑一个C ++抽象类的简单示例,用于建模接口:

class IAnimal
{
  virtual void walk()=0;
  virtual ~IAnimal(){}
};

是否更好地拥有析构函数?我不认为析构函数可以是纯虚拟的,至少我的测试会给链接器错误,所以是否应该包含空的析构函数?

编辑:抱歉,错字。它是一个析构函数而不是构造函数。

6 个答案:

答案 0 :(得分:43)

您应该始终使用带有接口的虚拟析构函数。一个很好的例子:

IAnimal* animal = new Lion();
delete animal;

现在它将使用什么析构函数?绝对不是Lion的析构函数,因为接口不知道Lion的析构函数

所以,如果您的界面没有内存管理,请使用此功能:

virtual ~IAnimal(){}

答案 1 :(得分:20)

查看Herb Sutter撰写的this文章

特别是这部分:

  

对于析构函数的特殊情况   只有:

     

准则#4:基类析构函数   应该是公共的和虚拟的,   或受保护和非虚拟。

这假设基类是一个“接口”类,因为它应该是。

答案 2 :(得分:5)

这取决于您是否打算使用指向接口类的指针以多态方式管理对象的生命周期。

如果这样做,那么析构函数必须是虚拟的,才能正确删除对象。删除没有虚析构函数的基类指针是无效的,并给出了未定义的行为。

如果不这样做,那么你应该通过使析构函数非虚拟和受保护来强制执行此操作,因此只能删除派生类。

答案 3 :(得分:1)

我认为它应该是接口的纯虚拟析构函数,所有其他方法也都是纯虚拟的。

答案 4 :(得分:0)

应该包含一个空构造函数,因为接口的典型用法是将指针放在容器中的某个具体对象上,否则将调用错误的析构函数并且不会正确地清理内存。 因此,如果有人要通过指向Ianimal的指针删除派生对象,则创建一个虚拟析构函数,否则使析构函数非虚拟化并受到保护。 使你的析构函数纯虚拟可能不是一个好主意,因为它强制派生类的实现者覆盖你的析构函数,尽管他们可能想要什么都不做

答案 5 :(得分:0)

不使析构函数成为虚拟的唯一原因是保存vptr所需的空间。因为你需要vptr,因为你有另一个虚函数,我会使析构函数变为虚拟。