当你有一个虚拟析构函数时,基类指针中的“删除这个”是否会删除派生类对象?

时间:2013-01-06 14:27:15

标签: c++ oop object virtual-destructor

我有一个三级深度的类层次结构,如下所示:

class A {
public: 
    virtual ~A() {}

}

class B : public A {
public:
    virtual ~B() {}
    void foo(E *e) {
        e->remove(this);
    }
}

class C : public B {
public:
    ~C() {}
}

class E {
public:
    void remove(A *a) {
        delete a;
    }
}

好的,我想知道当我在foo()的对象上调用C时会发生什么。它是要移除整个对象还是仅移除对象的BA部分,并将C部分留在内存中?

3 个答案:

答案 0 :(得分:5)

  

是要删除整个对象还是只删除对象的B和A部分,并将C部分留在内存中?

没有。它将“做正确的事”(即,删除最派生的子对象,运行其所有析构函数等)提供A(即指针指针的静态类型delete )有一个虚拟析构函数(如果类A有一个虚拟析构函数,它的所有后代都有它)。这也适用于多重继承。

答案 1 :(得分:2)

感谢A中的虚拟析构函数,代码可以正常销毁C的整个实例。

答案 2 :(得分:2)

delete将始终释放指向的整个对象的内存。 这不适用于被调用的析构函数:它将尝试调用要删除的对象的静态类型的析构函数。 在多态方案中,这通常不是您想要的。考虑一下:

struct Base { };

struct Derived : Base
{
    int* i;

    Derived() : i(new int) { }

    ~Derived() { delete i; }
}

void bad()
{
    Base* b = new Derived;
    delete b;
}

bad()导致内存泄漏,因为永远不会调用Derived的析构函数。这是因为b的静态类型是Base*,因此将调用Base::~BaseBase中没有定义析构函数,因此编译器提供的默认实现执行,在此特定示例中不执行任何操作。

然而,这不适用于您的示例:您使根类'析构函数为虚拟,因此所有派生类的析构函数将作为析构函数调用的一部分执行。