C++虚拟方法不起作用

Tim*_*man 3 c++ methods virtual inheritance function

给出以下示例:

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;
}
Run Code Online (Sandbox Code Playgroud)

当我删除我的派生类引用时,我将EXPECT流程如下:

  1. 执行Level2DerivedClass析构函数.
  2. 因为Level1DerivedClass析构函数是虚拟的,所以它将被执行.
  3. 因为BaseClass析构函数是虚拟的,所以它将被执行.
  4. 因为BaseClass :: CleanupLevel1DerivedClass :: Cleanup都是虚拟的,所以来自BaseClass析构函数中BaseClass "this"指针的调用将执行最派生类的实现 - Level2DerivedClass :: Cleanup.
  5. Level2DerivedClass :: Cleanup调用其父级的Cleanup实现.
  6. Level1DerivedClass :: Cleanup调用其父级的Cleanup实现.

正在发生的事情是,它正在调用每个级别的继承(1 - 3)的析构函数,超出了我期望的方式.但是当从BaseClass析构函数调用this-> Cleanup()时,它只执行自己的实现.我不明白为什么会发生这种情况,因为通常当您实例化派生类指针,将其转换为基类指针,并从基类指针调用虚方法(在本例中为'this')时,它仍会运行派生类实现('虚拟'的整点,是吗?).在我的示例中,从不调用Level2DerivedClass :: CleanupLevel1DerivedClass :: Cleanup.

我这样设置它的原因是我希望能够调用我的清理代码而不必销毁我的对象,这就是为什么我从实际的析构函数体中抽象它.

如果您对更合适的方法有建议,我会全力以赴.但我还想解释为什么我的设置不起作用 - 我误解了什么?

提前谢谢您的时间.

Oli*_*rth 7

经验法则是:在构造或销毁期间永远不要调用虚函数.

他们没有你所期望的那样行事; 当每个析构函数完成时,动态类型this被有效地修改.来自C++标准中的[class.cdtor]:

当从构造函数(包括用于非静态数据成员的mem-initializer或brace-or-equal-initializer)或从析构函数直接或间接调用虚函数时,调用所适用的对象是对象在构造或销毁中,调用的函数是在构造函数或析构函数自己的类或其基础中定义的函数,但不是在从构造函数或析构函数的类派生的类中重写它的函数,或者在其中一个类中覆盖它的函数.最派生对象的其他基类.