5

私は次の設定を正しくしようとしています:

class A特定のアプリケーション(複数のソースファイル、コンパイルユニットを含む)には、多くのコンパイルユニットで定義されたタイプのグローバル変数があります。class Bこれらは、作成時にクラスBのインスタンスに「登録」し、破棄時に「サインオフ」するという意味で、導入する新規(1つのインスタンスのみが存在する必要がある)によって「管理」される必要があります。

コンストラクターが機能するように設定するのはかなり簡単です。使用できるもの:

types.h

class B {
  static B& Instance() {
    static B singleton;
    return singleton;
  }
  void registerA( const A& a ) { 
  // whatever
  }
};


class A {
  A() { B::Instance().registerA( this ); }
};

破壊者を正しくする方法は?使用する場合:

class A {
  A() { B::Instance().registerA( this ); }
  ~A() { B::Instance().signoffA( this ); }
};

その場合、のデストラクタはのデストラクタのB前に呼び出される可能性がありAます。次に、クラスのインスタンスはA、新しく作成されたばかりののインスタンスでサインオフしますB

テストケースはclass A、名前空間内のインスタンスの定義を含むマルチソースファイルのセットアップになります。

file1.cc

#include "types.h"
namespace C {
   A a;
}

file2.cc

#include "types.h"
namespace C {
   A b;
}

Boostスマートポインタを使えば、そのようなことが簡単にできると思います。ただし、可能であれば、依存関係をできるだけ低く保つために追加のライブラリを使用することは避けたいと思います。

役立つかもしれない1つのこと:すべてのグローバル変数は名前空間にあります。

4

2 に答える 2

4

大丈夫だと思います。「終了」に関する3.6.3は次のとおりです。

静的ストレージ期間を持つオブジェクトのコンストラクターまたは動的初期化の完了が別のオブジェクトの完了よりも前にシーケンスされる場合、2番目のデストラクタの完了は、最初のデストラクタの開始の前にシーケンスされます。

次の設定があるとします。

struct A;

struct B
{
    static B & get() { static B impl; return impl; }
    void registrate(A *);

private:
    B() { /* complex stuff */ }
    // ...
};

struct A { A() { B::get().registrate(this); } };

A a1;

これで、何が起こっても、静的A型オブジェクトの最初のコンストラクターがを呼び出します。これは、最初のコンストラクターが完了する前にB::get()静的オブジェクトの構築をシーケンスします。上記の節により、これにより、-objectのデストラクタがすべての-destructorの後にシーケンスされることが保証されます。implAB implA

于 2012-05-19T18:11:23.567 に答える
2

Bインスタンスは静的であるため、シングルトンがA作成された後に作成されたインスタンスよりも長持ちします。B

于 2012-05-19T17:54:07.887 に答える