简体   繁体   English

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

[英]Calling child method from parent destructor in C++

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

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

When I delete B, only A class release() method is called. 当我删除B时,只调用一个类release()方法。

What I want to achieve is for every child object, when it is deleted, I want to call release method which is overriden in each child class, without manually specifying destructor for each child with call to release (I'm lazy). 我想要实现的是每个子对象,当它被删除时,我想调用在每个子类中重写的释放方法,而无需为每个调用release的子项手动指定析构函数(我是懒惰的)。 Is this actually not possible to achieve in this or any other way? 这实际上不可能以这种方式或任何其他方式实现吗?

Destructors are executed in the reverse order of constructors , so when the A in a B is destroyed its B component has already been destroyed and no longer exists. 析构函数构造的相反的顺序执行,所以当AB被破坏其B分量已经被销毁,并且不再存在。 Calling a method on a destroyed object yields undefined behavior , and that's why calls to virtual methods always resolve to the current class type within a constructor or destructor . 在被破坏的对象上调用方法会产生未定义的行为 ,这就是为什么对构造函数析构函数中的 虚方法的调用始终解析为当前类类型的原因。

So basically no, you cannot do it. 所以基本上没有,你不能这样做。 You will have to write them all. 你必须全部写出来。

Don't call virtual methods from destructors or constructors - they won't do what you expect them to do. 不要从析构函数或构造函数中调用虚方法 - 它们不会按照您的期望执行。

Quit being lazy and write destructors. 退出懒惰并编写析构函数。

A solution to this kind of problem is a pre-destroy phase, where you can manually control how destruction happens. 解决此类问题的方法是预破坏阶段,您可以手动控制破坏的发生方式。

Implement your object with the pImpl pattern. 使用pImpl模式实现您的对象。 When the wrapping object is destroyed, inform the pImpl that it is going to be destroyed before destroying it. 当包装对象被销毁时,通知pImpl它将在销毁之前被销毁。

pImpl can have a base virtual PreDestroyable class that allows child methods to register a PreDestruction callback, which you call during this pre destruction phase. 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() {}
};

I last wrote this stuff prior to C++11, so I haven't worked out how to handle move constructing it. 我上次在C ++ 11之前写过这些东西,所以我还没有弄清楚如何处理构造它的移动。 And it is all done at runtime, while it is probably possible to do something like the above with less runtime data. 它全部在运行时完成,而可能可以使用较少的运行时数据执行上述操作。 Something like a list of types in the hierarchy that contain pre-destroy code or something? 类似于层次结构中包含预破坏代码的类型列表?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM