C++工具箱(一)——单件模版类

来源:互联网 发布:创世写作软件 编辑:程序博客网 时间:2024/06/06 09:07

我们在工作中往往会用到单件类。但是我们知道单件类的实现就那么几步,如果系统中有多个单件类的话,去一个个写非常麻烦,那么怎么办呢?


单件模版类就派上用场了:

template <typename _CoClass>class Singleton{public:Singleton() {}virtual ~Singleton() {}static _CoClass& GetInstance(){if (!m_psInstance){m_psInstance = new _CoClass();}return *m_psInstance;}private:// 防止单件复制.Singleton(const Singleton& copy);Singleton& operator = (const Singleton& rhs);static _CoClass*m_psInstance;};//// 单件实例指针初始化.//template <typename _CoClass>_Coclass* Singleton<_CoClass>::m_psInstance = 0;
那么该怎么用呢?如下:

class CDataMgr : public Singleton<CDataMgr>{public:void SaveData();// ...};int main(){// ...CDataMgr::GetInstance().SaveData();}
只要我们需要让一个类成为单件,只需从 Singleton 模版派生即可。那么我们思考下为什么这个模版类是可以工作的。


如果你熟悉 WTL的话,这个例子非常容易看懂。首先,我们知道,在C++ 中,如果定义一个指针,是不需要看见它的类型的具体实现的,我们只需要这个类型的名字就行了——这就是“前向声明”为什么可以工作的原因——其实更深层次上,一个指针在Win32平台下,内存中都为其分配4字节,指针的类型只是给编译器看的。


其次,模版在实例化的过程中,不管谁包含了这个模版的头文件并以什么类型使用了这个模版,编译器将对一个类型只生成一份对应的实例。所以,如果我们的a.h里面实现了一个CMyClass的单件类,然后我们在a.cpp b.cpp中都包含了 a.h,因为模版实例化的特性,相对于Singleton<CMyClass>::m_psInstance 这个变量将只存在一份实例,不会在链接时出现多重定义的情况。


那么我们的 CDataMgr实例化后是什么情况呢?伪代码可能如下:

//// 编译器自动加上的前向声明.//class CDataMgr;//// 用 CDataMgr 实例化的单件基类.//class Singleton<CDataMgr>{public:// ...static CDataMgr& GetInstance(){// ...return *m_psInstance;}private:static CDataMgr*m_psInstance;};CDataMgr* Singleton<CDataMgr>::m_psInstance = 0;//// 编译器处理后的类 CDataMgr.//class CDataMgr : public Singleton<CDataMgr>{public:// ...void SaveData();};

这样一来,整个过程就非常容易理解了,这个模版使用起来非常方便。如果非常复杂的系统,还可以加上单件的管理,比如单件类初始化顺序管理、单件类释放顺序管理等等。