析构函数

时间:2015-09-08 22:36:34

标签: c++ destructor

在这个问题中:How do virtual destructors work?

最佳答案如下:

Note that the destructor of the base class will be called implicitly after the destructor of the derived class finishes. This is a difference to the usual virtual functions.

我整理了一个快速示例程序来测试它,

class A {
public:
  virtual ~A() {
    std::cout << "A DESTRUCTOR" << std::endl;
  }
};
class B {
public:
  virtual ~B() {
    std::cout << "B DESTRUCTOR" << std::endl;
  }
};
class C {
public:
  virtual ~C() {
    std::cout << "C DESTRUCTOR" << std::endl;
  }
};

int main(int argc, char** argv)
{
  A * aPtr = (A *)new C();
  C * cPtr = new C();

  delete aPtr;
  delete cPtr;
  return 0;
}

我得到的输出是

C DESTRUCTOR
C DESTRUCTOR

这似乎与说明不符。

我的问题是,如何在需要运行多个析构函数的类层次结构中安全地实现析构函数?

例如,假设A类和C类都在堆上分配了一个属性并需要清理它们。我怎样才能安全地编写这样的层次结构?注意:我目前没有尝试编写这样的层次结构,请不要回答“不要设计错误”#34;。此外,我理解智能指针可以解决问题,这更多的是确保我理解底层机制。

是否需要C类正确清理A类属性?如果该属性是私有而不是受保护或公开,会发生什么?我错过了什么,或者误解了我所看到的东西吗?

用于运行这些测试的编译器

gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4

4 个答案:

答案 0 :(得分:4)

  1. 您忘记了类之间的继承

  2. 只要您执行delete

    ,就会触发undefined behavior
    A * aPtr = (A *)new C();
    
  3. 我相信this就是您要搜索的内容

    class A {
    public:
      virtual ~A() {
        std::cout << "A DESTRUCTOR" << std::endl;
      }
    };
    class B : public A{
    public:
      virtual ~B() {
        std::cout << "B DESTRUCTOR" << std::endl;
      }
    };
    class C : public B{
    public:
      virtual ~C() {
        std::cout << "C DESTRUCTOR" << std::endl;
      }
    };
    
    int main(int argc, char** argv)
    {
      A * aPtr = new C(); // The cast here is not needed
      C * cPtr = new C();
    
      delete aPtr;
      delete cPtr;
      return 0;
    }
    

    输出

    C DESTRUCTOR
    B DESTRUCTOR
    A DESTRUCTOR
    C DESTRUCTOR
    B DESTRUCTOR
    A DESTRUCTOR
    

答案 1 :(得分:4)

正如其他人所说,你希望(确实需要)在这里使用继承。

他们没有注意到的是编译器只允许你这样做,因为你在 不应该拥有的地方使用了一个演员表。如果您需要使用演员表,那么真的应该坐下来,三思而后行为什么该演员表是必要的,并确保它所做的是真的你想做的事。

如果没有强制转换,编译器会阻止您的代码被破坏。如果继承得到纠正,没有演员就可以了:

#include <iostream>

class A {
public:
  virtual ~A() {
    std::cout << "A DESTRUCTOR" << std::endl;
  }
};
class B : public A {
public:
  virtual ~B() {
    std::cout << "B DESTRUCTOR" << std::endl;
  }
};
class C : public B {
public:
  virtual ~C() {
    std::cout << "C DESTRUCTOR" << std::endl;
  }
};

int main(int argc, char** argv) {
  A * aPtr = new C();

  delete aPtr;
}

结果:

C DESTRUCTOR
B DESTRUCTOR
A DESTRUCTOR

答案 2 :(得分:0)

更改为:

class A {
public:
  virtual ~A() {
    std::cout << "A DESTRUCTOR" << std::endl;
  }
};
class B : public A{
public:
  virtual ~B() {
    std::cout << "B DESTRUCTOR" << std::endl;
  }
};
class C : public B{
public:
  virtual ~C() {
    std::cout << "C DESTRUCTOR" << std::endl;
  }

};

答案 3 :(得分:0)

您在此处引用的行为是派生类中虚拟析构函数的行为,这意味着具有其他类继承的类。

还记得使用g ++进行c ++编译。