Singleton in C++

单件模式是一个常见的设计模式之一,它的主要作用是保证一个类的实例是全局唯一的,且是全局可见的。它的模板实现如下:

 代码

template<class T>
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>
*Singleton<T>::m_pInstance = 0;
代码
class Object
{
public:
    Object(){
}
    
void Print()
    {
        cout 
<< "Object::Print called" << endl;
    }
    
virtual ~Object(){}
};
 

 代码

int _tmain(int argc, _TCHAR* argv[])
{
    
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;删除,将会有内存泄漏的报告。这个实现方式和谁创建谁删除的原则相违背的,用户如果忘记删除对象,必然会造成内存泄漏。可以引入指针代理对象负责创建单件对象的创建和删除工作。 

代码
template<class T>
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响应的修改为:

代码
template<class T>
class Singleton
{
public:
    
static T& Instance()
    {
        
static PointerProxy<T> pointerProxy;
        
return pointerProxy.WrappedPointer();
    }
private:
    Singleton(
void){}
};

更改后的Singleton的使用如下:

代码
int _tmain(int argc, _TCHAR* argv[])
{
    
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继承私有构造函数的类。

class Sealed
{
private:
    Sealed(){};
};

最终版本的Singleton如下:

代码
template<class T>
class Singleton : virtual public Sealed
{
public:
    
static T& Instance()
    {
        
static PointerProxy<T> pointerProxy;
        
return pointerProxy.WrappedPointer();
    }
private:
    Singleton(
void){}
};

posted on 2010-04-06 13:18  回归的足迹  阅读(265)  评论(0)    收藏  举报