Singleton in C++
单件模式是一个常见的设计模式之一,它的主要作用是保证一个类的实例是全局唯一的,且是全局可见的。它的模板实现如下:
代码
class Singleton
{
public:
static T* Instance()
{
if(m_pInstance == 0)
m_pInstance = new T();
return m_pInstance;
}
private:
Singleton(void){}
static T *m_pInstance;
};
template<class T>
T *Singleton<T>::m_pInstance = 0;
};
template<class T>
T *Singleton<T>::m_pInstance = 0;
代码 {
public:
Object(){}
void Print()
{
cout << "Object::Print called" << endl;
}
virtual ~Object(){}
};
代码
{
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetDbgFlag( tmpFlag );
Object *instance = Singleton<Object>::Instance();
instance->Print();
delete instance;
return 0;
}
_tmain中启动了内存泄漏检测,代码如下:
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetDbgFlag( tmpFlag );
由于单件不允许有实例,因为没有公有的构造函数,所以析构函数也不可能被调用,在虚构函数中删除创建的对象也是毫无意义的。这就是说这个实现需要用户显式的删除单件创建的对象,如果将delete instance;删除,将会有内存泄漏的报告。这个实现方式和谁创建谁删除的原则相违背的,用户如果忘记删除对象,必然会造成内存泄漏。可以引入指针代理对象负责创建单件对象的创建和删除工作。
代码 class PointerProxy
{
public:
PointerProxy() : m_pWrappedPointer (new T()){}
~PointerProxy()
{
if(m_pWrappedPointer != NULL)
{
delete m_pWrappedPointer;
m_pWrappedPointer = NULL;
}
}
T &WrappedPointer()
{
return *m_pWrappedPointer;
}
private:
T* m_pWrappedPointer;
};
将Singleton响应的修改为:
代码 class Singleton
{
public:
static T& Instance()
{
static PointerProxy<T> pointerProxy;
return pointerProxy.WrappedPointer();
}
private:
Singleton(void){}
};
更改后的Singleton的使用如下:
代码 {
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetDbgFlag( tmpFlag );
Object& instance = Singleton<Object>::Instance();
instance.Print();
return 0;
}
对于基于模板的的Singleton而言,没有必要从Singleton派生新的单件出来,因此可以将它作为密封类来实现,即通过virtual继承私有构造函数的类。
{
private:
Sealed(){};
};
最终版本的Singleton如下:
代码 class Singleton : virtual public Sealed
{
public:
static T& Instance()
{
static PointerProxy<T> pointerProxy;
return pointerProxy.WrappedPointer();
}
private:
Singleton(void){}
};
代码
浙公网安备 33010602011771号