代码之家  ›  专栏  ›  技术社区  ›  Mr. Boy

C++'接口是否有虚拟析构函数[复制]

c++
  •  41
  • Mr. Boy  · 技术社区  · 14 年前

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

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

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

    是否最好有析构函数?我认为析构函数不能是纯虚拟的,至少我的测试会给出链接器错误,那么应该包括一个空的析构函数吗?

    编辑: 对不起,打字错误。它是一个析构函数而不是构造函数。

    6 回复  |  直到 6 年前
        1
  •  41
  •   Kirill V. Lyadvinsky    14 年前

    您应该始终使用带有接口的虚拟析构函数。例证:

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

    现在它将使用什么析构函数?显然不是lion的析构函数,因为接口 不知道狮子的毁灭者 .

    因此,如果您的接口没有内存管理,请使用此选项:

    virtual ~IAnimal(){}
    
        2
  •  20
  •   adem    6 年前

    退房 this 文章作者:Herb Sutter

    尤其是这部分:

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

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

    这假设基类是一个“interface”类,因为它通常应该是这样的。

        3
  •  5
  •   Mike Seymour    14 年前

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

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

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

        4
  •  1
  •   duffymo    14 年前

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

        5
  •  0
  •   gpeche    14 年前

    不使析构函数成为虚拟的唯一原因是为了节省 vptr . 正如你需要的 VPTR 无论如何,因为您有另一个虚拟函数,所以我将使析构函数成为虚拟的。

        6
  •  0
  •   flownt    14 年前

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