给出以下示例:

class BaseClass
{
  BaseClass()
  {
  };

  virtual ~BaseClass()
  {
    this->Cleanup();
  };

  virtual void Cleanup()
  {
    // Do cleanup here.
  };
};

class Level1DerivedClass : public BaseClass
{
  Level1DerivedClass()
  {
  };

  virtual ~Level1DerivedClass()
  {
  };

  virtual void Cleanup()
  {
    // Call my base cleanup.
    BaseClass::Cleanup();

    // Do additional cleanup here.
  };
};

class Level2DerivedClass : public Level1DerivedClass
{
  Level2DerivedClass()
  {
  };

  ~Level2DerivedClass()
  {
  };

  void Cleanup()
  {
    // Call my base cleanup.
    Level1DerivedClass::Cleanup();

    // Do additional cleanup here.
  };
};


main()
{
  Level2DerivedClass * derived2 = new Level2DerivedClass();
  delete derived2;
  return 0;
}

当我删除派生类引用时,我将 EXPECT 流程如下:
  • Level2DerivedClass析构函数已执行。
  • 因为Level1DerivedClass析构函数是虚拟的,所以将执行它。
  • 因为BaseClass析构函数是虚拟的,所以将执行它。
  • 因为BaseClass::Cleanup和Level1DerivedClass::Cleanup都是虚拟的,所以从BaseClass析构函数中的BaseClass'this'指针进行的调用将执行派生程度最高的类Level2DerivedClass::Cleanup的实现。
  • Level2DerivedClass::Cleanup调用其父级的Cleanup实现。
  • Level1DerivedClass::Cleanup调用其父级的Cleanup实现。

  • 发生的事情是,它正在按我期望的方式为每个继承级别(1-3)调用析构函数。但是,当从BaseClass析构函数调用this-> Cleanup()时,它仅执行自己的实现。我不明白为什么会这样,因为通常在实例化派生类指针,将其转换为基类指针并从基类指针调用虚拟方法(在本例中为“this”)时,它仍然运行派生类的实现(整个“虚拟”点,是吗?)。在我的示例中,永远不会调用Level2DerivedClass::Cleanup和Level1DerivedClass::Cleanup。

    我以这种方式进行设置的原因是,我希望能够调用我的清理代码而不必破坏我的对象,这就是为什么我要从实际的析构函数主体中抽象出来。

    如果您对采取更适当的方法有任何建议,我非常高兴。但是我也想解释一下为什么我的设置不起作用-我误会了什么?

    预先感谢您的宝贵时间。

    最佳答案

    经验法则是:Never Call Virtual Functions during Construction or Destruction

    他们的行为不像您预期​​的那样。随着每个析构函数的完成,this的动态类型将得到有效修改。在C++标准的[class.cdtor]中:

    10-06 15:14