コンストラクタまたはデストラクタで静的オブジェクトによって使用されるオブジェクトが必要な場合は、通常、シングルトン パターンのバリエーションを使用するのが最善です。これにより、初期化の問題の順序が解決されます。正しく行えば、オブジェクトは破棄されないため、破棄の順序の問題も発生しないはずです。
アプリケーションは明らかにマルチスレッド化されているため (mutex があるため)、main に入る前に確実に初期化することにより、オブジェクトをスレッドセーフにする通常の予防策を講じる必要があります。基本的な考え方は次のようなものです。
template <typename T, char const* id>
class StaticInstanceWrapper
{
static T* myObject;
public:
static T& instance();
};
template <typename T, char const* id>
T* StaticInstanceWrapper<T, char const* id>::myObject =
&StaticInstanceWrapper<T>::instance();
template <typename T, char const* id>
T& StaticInstanceWrapper<T>::instance()
{
if ( myObject == NULL ) {
myObject = new T;
}
return *myObject;
}
次に、静的オブジェクトを として定義し、だけではなく
static
StaticInstanceWrapper<Whatever> obj;
としてアクセスします
(メンバーがないため、コンパイルされません)。obj.instance().someFunction()
obj.someFunction()
obj
someFunction()
のインスタンスごとStaticInstanceWrapper
に異なる型を持ち、一意の静的メンバーを持つには、テンプレートの個別のインスタンス化を強制する必要があることに注意してください。id
これが、テンプレート引数を使用する理由です。この引数の型は、各インスタンスが一意の識別子を持っている限り、実際には何でもかまいません。実際には、おそらく定義にマクロを使用します。次のようなものです。
#define DEFINE_STATIC_INSTANCE_WRAPPER(type, name) \
char const PASTE(name, _Identifier)[] = STRINGIZE(name); \
StaticInstanceWrapper<type, PASTE(name, _Identifier)> name
これにより、各インスタンスが一意の ID を持つことが保証されます。(より手の込んだものにしたい場合は、マングルすることもできますが__LINENO__
、名前はスコープ内で一意でなければならないため、これが必要であるとは思えません。)