如果您需要静态对象使用的对象,在构造函数或析构函数中,通常最好使用单例模式的变体。这样就解决了初始化顺序的问题,如果做对了,对象永远不会被破坏,所以也不应该有破坏顺序的问题。
由于您的应用程序显然是多线程的(因为您有一个互斥锁),您应该采取通常的预防措施来确保对象线程安全,确保在进入 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__
,但由于无论如何名称必须在范围内是唯一的,我怀疑这是必要的。)