这里没有定义虚拟析构函数

时间:2015-04-05 03:56:47

标签: c++

这已在我的官方说明中提供,但我发现了一个错误。在我把它交给我的导师之前,我只是想在这里与我所有的血兄弟一起确认 - 你们。

#include <iostream.h>

class Base {
   public:
      virtual void display() { cout << "Base class" << endl; }
};

class Derived: public Base {
   // Nothing here
};

void main()
{
   Base * ptr;
   // Calls Base::display ( )
   ptr = new Base ;
   ptr ->display();
   delete ptr ;
   // Calls Base::display ( ) again
   ptr = new Derived ;
   ptr ->display();
   delete ptr ;
}

输出结果为:

Base class 
Base class

我认为问题出在主要功能的最后一行。我的意思是,由于析构函数不是虚拟的,我认为你不能使用基类类型的指针删除动态分配的派生类类型的实例。你怎么看?

2 个答案:

答案 0 :(得分:1)

  

我的意思是,由于析构函数不是虚拟的,我认为你不能使用基类类型的指针删除动态分配的派生类类型的实例。你觉得怎么样?

您可以看到herehere这是未定义的行为。

  

如果基类没有虚析构函数,那么这些代码的行为就是未定义的。

  

来自C ++标准:

     

5.3.5删除

     

3在第一个备选(删除对象)中,如果操作数的静态类型与其动态类型不同,则静态类型应为操作数的动态类型的基类,静态类型应具有虚拟析构函数或行为未定义。

答案 1 :(得分:0)

当一个函数被定义为virtual时,编译器将使用 dynamic binding 使用指向base的指针来调用该函数,即对实际函数的调用将通过类vTable来查找相关的功能实现。如果函数未定义为虚拟,那么编译器生成的代码将使用静态绑定,即编译器将只调用它知道的函数。换句话说,如果在基类指针上调用指向派生类的非虚函数,则编译器将生成用于调用基类实现的代码。

现在,析构函数行为只是上述一般行为的私有情况。由于没有析构函数实现,编译器将为您生成一个默认的非虚析构函数,使用基类指针销毁对象只会调用基类析构函数。您可以通过显式定义基类和派生类的非虚拟析构函数来轻松地重现此行为,并使用调试器查看基类版本是被调用的版本。