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

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


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

template 
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 
_Coclass* Singleton<_CoClass>::m_psInstance = 0;
那么该怎么用呢?如下:

class CDataMgr : public Singleton
{
public:
	void SaveData();
	
	// ...
};


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


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


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


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

//
// 编译器自动加上的前向声明.
//
class CDataMgr;

//
// 用 CDataMgr 实例化的单件基类.
//
class Singleton
{
public:
	// ...
	
	static CDataMgr& GetInstance()
	{
		// ...
		return *m_psInstance;
	}
	
private:
	static CDataMgr*	m_psInstance;
};


CDataMgr* Singleton::m_psInstance = 0;


//
// 编译器处理后的类 CDataMgr.
//
class CDataMgr : public Singleton
{
public:
	// ...
	
	void SaveData();
};

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





你可能感兴趣的:(C/C++,C++工具箱)