关于Singleton模式

GuanXP 2001-12-31 01:12:54
这里讨论Singleton模式在c++中的对象释放问题.
一般的,一个Singleton类如下:
//--------------------------
// Singleton.h
//--------------------------
class CSingleton
{
protected:
CSingleton ();
~CSingleton ();
public:
static CSingleton* Instance();
private:
static CSingleton * s_pInstance;
};
//--------------------------
// Singleton.cpp
//--------------------------
CSingleton * CSingleton ::s_pInstance=NULL;
CSingleton ::CSingleton (){}
CSingleton :~CSingleton (){}
CSingleton* CSingleton::Instance()
{
if(!s_pInstance)
s_pInstance=new CSingleton;//创建唯一对象
return s_pInstance;
}
此模式是c的全局变量在c++中的面向对象的替代品.因为可能有多个客户对象引用
同一个CSingleton对象,为避免删除时的悬挂指针问题,要将CSingleton的
destructor声明为protected.这样客户就不能删除CSingleton对象了.但这也带
来了CSingleton类的资源释放问题.资源泄漏客户不能解决,所以必须由对象自己
解决.下面是两个解决办法.
1.引入一个管理器来管理所有的Singleton类.而这个类有一个静态实例,在程序退
出或模块卸载时,此静态实例的destructor会被调用,在此destructor中释放它
管理的所有Singleton对象.让所有的Singleton类都从一个基类派生,在基类的
constructor中向管理器注册,而在destructor中从管理器中反注册.

//-----------------------------------------------------
// SingletonBase.h
//-----------------------------------------------------
#ifndef _SINGLETON_BASE_HEADER_
#define _SINGLETON_BASE_HEADER_

#include <vector>
using namespace std;

class CSingletonBase
{
protected:
CSingletonBase ();
public:
virtual ~CSingletonBase ();
private:
class Manager//管理器类
{
vector<CSingletonBase *> m_Singletons;
public:
Manager();
~Manager();
void Register(CSingletonBase * pObj);
void Unregister(CSingletonBase * pObj);
};
static Manager s_Manager;
};
#endif
//-----------------------------------------------------
// SingletonBase.cpp
//-----------------------------------------------------
#include "SingletonBase.h"
#include <algorithm>
CSingletonBase::Manager::Manager(){}
CSingletonBase::Manager::~Manager()//Destructor of the manager
{
for(unsigned int i=m_Singletons.size();i>0;--i)
{
delete m_Singletons[i-1];//释放资源
}
}
void CSingletonBase::Manager::Register(CSingletonBase* pObj)
{
m_Singletons.push_back(pObj);
}
void CSingletonBase::Manager::Unregister(CSingletonBase* pObj)
{
vector<CSingletonBase *>::iterator it;
it=find(m_Singletons.begin(),m_Singletons.end(),pObj);
if(it!=m_Singletons.end())
{
if(*it)
{
*it=NULL;
m_Singletons.erase(it);
}
}
}
//*****************************************************
CSingletonBase::Manager CSingletonBase::s_Manager;//管理器的静态实例

CSingletonBase::CSingletonBase()
{
s_Manager.Register(this);
}

CSingletonBase::~CSingletonBase()
{
s_Manager.Unregister(this);
}
//--------------------------
// Singleton.h
//--------------------------
#ifndef _SINGLETON_HEADER_
#define _SINGLETON_HEADER_

#include "SingletonBase.h"

class CSingleton:protected CSingletonBase
{
protected:
CSingleton ();
~CSingleton ();
public:
static CSingleton* Instance();
private:
static CSingleton * s_pInstance;
};
#endif
//--------------------------
// Singleton.cpp
//--------------------------
CSingleton * CSingleton ::s_pInstance=NULL;
CSingleton ::CSingleton (){}
CSingleton :~CSingleton (){}
CSingleton* CSingleton::Instance()
{
if(!s_pInstance)
s_pInstance=new CSingleton;
return s_pInstance;
}
2.同样的思想,只是将管理器分布于各个具体的singleton类中,由于所有的
管理器都有相同的行为,所以用模板来实现.
//--------------------------
// SingletonManager.h
//--------------------------
#ifndef _TEMPLATE_SINGLETON_HEADER_
#define _TEMPLATE_SINGLETON_HEADER_
template<class T> class TSingletonManager
{
public:
TSingletonManager(T*& rlpT):m_rlpT(rlpT){}
virtual ~TSingletonManager(){if (m_rlpT) delete m_rlpT;}
private:
T*& m_rlpT;
};
#endif
//--------------------------
// Singleton.h
//--------------------------
#ifndef _SINGLETON_HEADER_
#define _SINGLETON_HEADER_

#include "SingletonManager.h"

class CSingleton
{
friend TSingletonManager<CSingleton>;
protected:
CSingleton ();
~CSingleton ();
public:
static CSingleton* Instance();
private:
static CSingleton * s_pInstance;
//管理器
static TSingletonManager<CSingleton > s_SingletonManager;
};
#endif
//--------------------------
// Singleton.cpp
//--------------------------
CSingleton * CSingleton ::s_pInstance=NULL;
CSingleton ::TSingletonManager<CSingleton >
s_SingletonManager(CSingleton ::s_pInstance);
CSingleton ::CSingleton (){}
CSingleton :~CSingleton (){}
CSingleton* CSingleton::Instance()
{
if(!s_pInstance)
s_pInstance=new CSingleton;
return s_pInstance;
}
如果使用COM的引用计数技术,那麽将delete都改为Release(),可以让
客户也能够参与到Singleton对象的资源释放,可能更好.

方法1让继承层次复杂化,但子类比较简单.方法2避免了继承,但对子类的
实现要求更多.各有利弊,怎麽使用,自己权衡.也可以用smart pointer
来实现资源的自动释放,但本人并不喜欢,连C++标准的auto pointer都
变来变去,你怎麽敢使用它?
...全文
103 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

15,440

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 非技术区
社区管理员
  • 非技术区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧