c++中从父析构函数调用子方法

Calling child method from parent destructor in C++

本文关键字:函数调用 子方法 析构 c++      更新时间:2023-10-16
class A {
public:
  ~A() { release(); }
  virtual release() { cout << "~A"; } 
}
class B : public A {
  release() { cout << "~B"; }
}

当我删除B时,只调用A类的release()方法。

我想要实现的是对于每个子对象,当它被删除时,我想要调用释放方法,该方法在每个子类中被覆盖,而无需手动指定每个子类的析构函数调用释放(我很懒)。难道这真的不可能通过这种方式或其他方式实现吗?

析构函数的执行顺序与构造函数相反,因此当B中的A被销毁时,其B组件已经被销毁,不再存在。在被销毁的对象上调用方法会产生未定义行为,这就是为什么调用虚方法总是解析为构造函数析构函数中的当前类类型。

所以基本上不,你不能这样做。

不要从析构函数或构造函数中调用虚方法——它们不会做你期望它们做的事情。

不要偷懒,写析构函数

这种问题的解决方案是预销毁阶段,在此阶段您可以手动控制销毁如何发生。

pImpl模式实现对象。当包装对象被销毁时,在销毁它之前通知pImpl它将被销毁。

pImpl可以有一个基本的virtual PreDestroyable类,允许子方法注册PreDestruction回调,在预销毁阶段调用。

class Destroyable {
protected:
  Destroyable() {}; // must be empty
  virtual ~Destroyable() { Assert(PreDestroyers.empty()); };
  void RegisterPreDestroy( std::function<void()> const& func ) { PreDestroyers.push_back(func) );
private:
  std::vector<std::function<void()>> PreDestroyers;
public:
  // reverse order, reentrant:
  void PrepareToDie() {
    while (!PreDestroyers.empty()) {
      auto f = PreDestroyers.back();
      PreDestroyers.pop_back();
      f();
    }        
  }
};
// handles registration:
template<typename T>
class HasPreDestroyCode: public virtual Destroyable {
  // TODO: usual CRTP static or dynamic checks:
  T* self() { return static_cast<T*>(this); }
  T const* self() const { return static_cast<T*>(this); }
  HasPreDestroyCode() {
    RegisterPreDestroy( [&]() { self()->PreDestroy(); } );
  }
  HasPreDestroyCode( HasPreDestroyCode const& other ) {
    RegisterPreDestroy( [&]() { self()->PreDestroy(); } );
  }
  HasPreDestroyCode( HasPreDestroyCode const& other ) {
    RegisterPreDestroy( [&]() { self()->PreDestroy(); } );
  }
private:
  HasPreDestroyCode& operator=( HasPreDestroyCode const& other ) = delete;
};
class Test: HasPreDestroyCode<Test> {
public:
  void PreDestroy() {}
};

我最后一次写这个东西是在c++ 11之前,所以我还没有弄清楚如何处理move构造它。所有这些都是在运行时完成的,而使用更少的运行时数据也可能完成类似上述的事情。比如包含预销毁代码的层次结构中的类型列表之类的东西?