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

时间:2012-12-22 17:42:42

标签: c++

class A {
public:
  ~A() { release(); }
  virtual release() { cout << "~A"; } 
}

class B : public A {
  release() { cout << "~B"; }
}

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

我想要实现的是每个子对象,当它被删除时,我想调用在每个子类中重写的释放方法,而不需要为每个调用release的子项手动指定析构函数(我是懒惰的) 。这实际上不可能以这种方式或任何其他方式实现吗?

3 个答案:

答案 0 :(得分:6)

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

所以基本上没有,你不能这样做。你必须全部写下来。

答案 1 :(得分:3)

不要从析构函数或构造函数中调用虚方法 - 它们不会按照您的期望来执行。

退出懒惰并编写析构函数。

答案 2 :(得分:3)

此类问题的解决方案是预破坏阶段,您可以手动控制破坏的发生方式。

使用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之前写过这些东西,所以我还没有弄清楚如何处理构造它的移动。它全部在运行时完成,而可能可以使用较少的运行时数据执行上述操作。类似于层次结构中包含预破坏代码的类型列表?