C++虚拟方法不起作用

标签 c++ function inheritance methods virtual

给定以下示例:

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::CleanupLevel1DerivedClass::Cleanup 都是虚拟的,BaseClass 中的“this”指针的调用 < em>BaseClass 析构函数将执行最派生类的实现 - Level2DerivedClass::Cleanup
  5. Level2DerivedClass::Cleanup 调用其父级的Cleanup 实现。
  6. Level1DerivedClass::Cleanup 调用其父级的Cleanup 实现。

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

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

如果您对执行此操作的更正确方法有任何建议,我会洗耳恭听。但我还想解释为什么我的设置不起作用 - 我误解了什么?

提前感谢您的宝贵时间。

最佳答案

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

他们的行为并不像您预期​​的那样;当每个析构函数完成时,this 的动态类型被有效修改。来自 C++ 标准中的 [class.cdtor]:

When a virtual function is called directly or indirectly from a constructor (including the mem-initializer or brace-or-equal-initializer for a non-static data member) or from a destructor, and the object to which the call applies is the object under construction or destruction, the function called is the one defined in the constructor or destructor’s own class or in one of its bases, but not a function overriding it in a class derived from the constructor or destructor’s class, or overriding it in one of the other base classes of the most derived object.

关于C++虚拟方法不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10820974/

相关文章:

java - 私有(private)成员可通过公共(public)方法访问

html - 如何使用 html 列表格式在 qt 工具提示中缩小缩进?

c++ - Boost.Program_options 固定数量的 token

MySQL - 可以调用函数来执行触发器操作吗?

c++ - 如何通过派生类的方法通过复制来设置基类字段?

java - 使用继承时,静态 block 和初始化 block 按什么顺序执行?

c++ - 如何使用 composite_key 为 multi_index_container 编写自定义谓词?

c++ - std::set<T>::erase(key)。如果没有 key 怎么办?

C++ 用函数替换代码的最佳方法

php - 我应该将 $mysqli 变量传递给每个函数吗?