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

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

B を削除すると、A クラスの release() メソッドのみが呼び出されます。

私が達成したいのは、すべての子オブジェクトに対して、それが削除されたときに、リリースへの呼び出しで各子のデストラクタを手動で指定せずに、各子クラスでオーバーライドされる release メソッドを呼び出したいことです (私は怠け者です)。これは実際にこれまたは他の方法で達成することはできませんか?

4

3 に答える 3

7

デストラクタはコンストラクタと逆の順序で実行されるため、Ain aBが破棄されると、そのBコンポーネントはすでに破棄されて存在しなくなります。破棄されたオブジェクトでメソッドを呼び出すと、未定義の動作が発生します。これが、仮想メソッドの呼び出しが常にコンストラクターまたはデストラクター内の現在のクラス型に解決される理由です。

基本的にいいえ、あなたはそれをすることはできません。それらをすべて書く必要があります。

于 2012-12-22T17:45:08.657 に答える
3

デストラクタまたはコンストラクタから仮想メソッドを呼び出さないでください。期待どおりの動作をしません。

怠け者になるのをやめて、デストラクタを書きましょう。

于 2012-12-22T17:45:25.913 に答える
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 より前にこのようなものを最後に書いたので、それを構築する移動を処理する方法を考え出していませんでした。そして、それはすべて実行時に行われますが、上記のようなことをより少ない実行時データで行うことはおそらく可能です。破棄前のコードなどを含む階層内の型のリストのようなものですか?

于 2012-12-22T18:18:04.047 に答える