【问题标题】:Will "delete this" in a base class pointer delete the derived class object when you have a virtual destructor?当你有一个虚拟析构函数时,基类指针中的“删除这个”会删除派生类对象吗?
【发布时间】:2012-12-20 10:06:39
【问题描述】:

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

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;
    }
}

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

【问题讨论】:

  • 您有语法错误。请修复它们。另外,避免像瘟疫一样避免delete this。另外,void remove(A* a)class E 中,但void remove(E* e)class B 中?你确定吗?哎呀!
  • 你正在销毁所有对象,并释放它的内存。
  • 您的代码中有 2 个删除项。哪一个?
  • 析构函数的虚拟性是遗传的。
  • 在删除 A 后尝试访问 B 类实例的方法是另一种检查方法。

标签: c++ oop object virtual-destructor


【解决方案1】:

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

没有。如果A(即delete的指针的指针的静态类型)有一个virtual析构函数(如果 A 类有一个虚拟析构函数,它的所有后代也都有它)。这也适用于多重继承。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 所有编译器都这样吗?我发誓我已经看到 C 在没有 A 声明虚拟析构函数的情况下被破坏。主要在 gcc 中。
    【解决方案3】:

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

    struct Base { };
    
    struct Derived : Base
    {
        int* i;
    
        Derived() : i(new int) { }
    
        ~Derived() { delete i; }
    }
    
    void bad()
    {
        Base* b = new Derived;
        delete b;
    }
    

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

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

    【讨论】:

      猜你喜欢
      • 2011-03-16
      • 2020-12-27
      • 1970-01-01
      • 1970-01-01
      • 2010-10-15
      • 1970-01-01
      • 2012-02-05
      • 2017-08-08
      相关资源
      最近更新 更多