我何时/何时使用虚拟析构函数?

时间:2010-12-04 00:11:43

标签: c++ inheritance polymorphism destructor

我目前正在编写一个具有以下多态层次结构的程序:Base:Multinumber。派生:对,复杂,理性。 Multinumber是一个虚拟类,从不实例化。

在我的程序过程中,我经常动态管理基类,所以我需要一个析构函数。我的问题是:如何使析构函数虚拟化?在我的Multinumber.h文件中,我现在有这个:

  virtual ~Multinumber();

在我的Multinumber.cpp中:

Multinumber::~Multinumber()
{
}

在我的所有派生类中,我都有:

Rational::~Rational()
{
}

我的任何deri.h文件中都没有任何内容。不幸的是,这不编译。相反,我得到了这个错误:

Complex.cpp|75|error: definition of implicitly-declared 'virtual Complex::~Complex()'

我的语法有什么问题?谢谢你能给我的任何帮助。

5 个答案:

答案 0 :(得分:4)

在基数中声明virtual析构函数,并为其赋予空定义就足够了。对于其他课程,你根本不需要做任何事情,除非那些析构函数的实际工作要做。

基类中virtual声明的要点是确保可以多态调用析构函数(以便Base* d = new Derived(); delete d;正常工作,调用派生析构函数而不是Base析构函数)。然后,您必须定义该析构函数(即使它不起作用),因为您声明了它。

但是,对于所有派生类,如果您没有指定任何内容,则会为它们生成默认的“成员和基础的调用析构函数”析构函数,并且一切都按您的需要工作。除非你再次需要做任何其他事情来正确破坏对象。

正如Dark Falcon指出的那样,你需要在基础上为你定义的每个成员做一个声明,包括析构函数。因此,如果您确实编写了Complex ::〜Complex,那么它必须在Complex类定义中声明,即使您从声明和定义析构函数的类继承。 (析构函数,就像构造函数一样,实际上并不是继承的;默认的“在成员和基础上递归调用”行为并不是真的相同。这些函数是特殊的,因为它们管理对象的生命周期,而不是使用对象。 )

答案 1 :(得分:3)

在Complex类中,您还需要声明析构函数:

~Complex();

请注意,虚拟是可选的。析构函数将是虚拟的,因为base的析构函数是虚拟的。

答案 2 :(得分:2)

何时声明析构函数是虚拟的?

我建议您按照此算法来决定是否应该声明析构函数是否为虚拟。

  

您的课程是否打算用作基类?

  • 否:声明非虚拟析构函数(避免在类的每个对象上使用v-pointer)并记住不要从具体类派生。
  • 是:转到下一个问题。
  

您的基类是抽象的吗? (即任何虚拟纯方法?)

  • 否:尝试通过重新设计层次结构[1]来使基类抽象化(即不允许基类实例化)。
  • 是:转到下一个问题。
  

您是否希望通过基指针允许多态删除?

  • 否:声明受保护的虚拟析构函数以避免不必要的使用。
  • 是:声明公共虚拟析构函数(在这种情况下没有开销)。

参考文献:

[1]:S。Meyers。更有效的C ++,第33项(Addison-Wesley,1996)。

[2]:“虚拟”http://www.gotw.ca/publications/mill18.htm

答案 3 :(得分:0)

  

我的语法有什么问题?

以下内容:

  

在我的所有派生类中,我   有这个:

     

Rational :: ~Rational(){}

不,不。您没有为Complex执行此操作。

答案 4 :(得分:0)

问题是:何时不声明析构函数是虚拟的?声明析构函数虚拟没有任何缺点。