C ++中的虚拟析构函数

时间:2015-04-05 04:18:40

标签: c++

我真的已经完成了现有的问题,我仍然需要回答这个问题才能真正了解我是否理解这一点。

通常,我们定义自己的析构函数的唯一时间是在内存上动态分配内容。

但是,我们仍然需要实现我们自己的析构函数(即使在堆上没有动态分配)只是为了将其命名为虚拟(如果我们没有在堆上分配任何内容,它可以只是纯虚拟的)使用基类地址(指针/引用)来访问派生类的对象。这是(我的推论)无条件正确吗?

因为如果有:

Base* p = new Derived;

现在要删除p,即空闲内存,我们必须将析构函数声明为虚拟并执行:

delete p;

正确?

3 个答案:

答案 0 :(得分:1)

  

Base* p = new Derived;

  现在要删除p,即空闲内存,我们必须将析构函数声明为虚拟并执行:

     

delete p;

  正确的吗?

作为这个问题的答案(Does delete work with pointers to base class?也说明了。

  

是的,当且仅当基类析构函数是虚拟

时才会起作用

C ++ 11

如果析构函数的实现很简单,你可以这样做

virtual ~Base() = default;

此外,派生类型应该使用override

virtual ~Derived() override = default;
^^^1^^^            ^^^2^^^^
// 1: Optional because the base destructor is virtual
// 2: The compiler will verify the base destructor is virtual

答案 1 :(得分:0)

是。最好假设存在需要运行析构函数的子类,因此虚拟析构函数需要存在于Base中。此外,即使在任何析构函数中没有代码的情况下,预计在销毁时也会发生其他事情。

class Derived : public Base {
    MyMember m;
}

如果Base上没有虚拟析构函数,当您以多态方式删除m时,永远不会调用Base*的析构函数。

如果您计划允许Base为任意子类进行子类化,则需要Base具有虚拟析构函数,以便安全地删除这些子类。

不建议考虑Base的非虚拟析构函数,因为您需要保证所有子类不仅没有析构函数,而且它们都没有析构函数的成员 ...这意味着没有stl容器或对象中的任何其他东西。其他开发人员很容易忽略这些奇怪的需求,因此您应该在Base中拥有一个虚拟析构函数。

答案 2 :(得分:0)

您只需要使基类的析构函数为虚拟。派生类可以显式定义析构函数,也可以使用构造函数定义的隐式析构函数。

struct Base
{
   virtual ~Base() {}
};

struct Derived1 : public Base
{
   // Explicitly defined destructor.
   // Use of virtual is optional.
   ~Derived () {}
   std::vector<std::string>> data;
};

struct Derived2 : public Base
{
   // Use the compiler defined destructor
   std::vector<int>> data;
};

用法:

Base* p = new Derived1;
...
delete p;   // OK

p = new Derived2;
...
delete p;   // OK