C++虚拟方法不起作用

C++ virtual method not working

本文关键字:不起作用 方法 虚拟 C++      更新时间:2023-10-16

给定以下示例:

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

当我删除派生类引用时,我希望流程如下所示:

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

正在发生的事情是,它调用每个继承级别 (1 - 3) 的析构函数高于我预期的方式。但是当从 BaseClass 析构函数调用 this->Cleanup() 时,它只执行自己的实现。我不明白为什么会发生这种情况,因为通常当您实例化派生类指针,将其转换为基类指针,并从基类指针调用虚拟方法(在本例中为"this")时,它仍然运行派生类实现("虚拟"的全部意义,是吗?在我的示例中,Level2DerivedClass::Cleanup 和 Level1DerivedClass:Cleanup 永远不会被调用。

我以这种方式设置它的原因是我希望能够在不必破坏我的对象的情况下调用我的 Cleanup 代码,这就是我从实际析构函数主体中抽象它的原因。

如果您对更正确的方法有建议,我都听见了。但我也想解释一下为什么我的设置不起作用 - 我误解了什么?

提前感谢您的时间。

经验法则是:切勿在构建或销毁期间调用虚拟函数

它们的行为与预期不同;当每个析构函数完成时,this的动态类型将得到有效修改。 从 C++ 标准中的 [class.cdtor] :

当从构造函数(包括 mem 初始值设定项或 非静态数据成员的大括号或等于初始值设定项)或析构函数,以及 调用应用是正在构建或销毁的对象,调用的函数是 构造函数或析构函数自己的类或其基之一,但不是派生类中重写它的函数 从构造函数或析构函数的类中重写它,或在派生最多的基类的其他基类之一中重写它 对象。

正确的做事方式是:在析构函数中清理自己,并且只清理自己。 不要在你的孩子或你的父母之后打扫。

如果你想清理不是来自析构函数的东西,你做错了。在C++我们有一个名为RAII的小东西,资源获取是初始化。但也有它的双重,它似乎没有一个正式的名字,但这里有一些可以工作的东西:RDID,资源处置是破坏。

当然,您不必坚持RAII/RDID的理念,但这不是C++的方式。