前一段时间面试豌豆荚的一道题,今天参见网上的一些博客,加上自己的理解写了一个觉得比较符合面试官当时意愿的Singleton
1. Singleton模板
Singleton.h 采用模板机制,使用产生确定类型的singleton类。 顺便说一下比较混淆的类模板和模板类。类模板首先是模板,用于产生类;而模板类是由这些类模板产生的类。比如:
template <typename T>
class vector
{
…
}; 就是一个类模板,而像vector <int>,vector <bool>等就是模板类。那么这个singleton是什么你就懂得了,(^__^) ...
#include <memory>
#include <iostream>
#include "Lock.h"
using namespace std;
template <class T>
class Singleton
{
public:
static inline T* Instance();
private:
Singleton(){}
~Singleton(){}
Singleton(const Singleton&){}
Singleton & operator= (const Singleton &){}
static auto_ptr<T> _instance;
static Lockdown _lk;
};
template <class T>
//Initialise,point to nothing
auto_ptr<T> Singleton<T>::_instance;
template <class T>
Lockdown Singleton<T>::_lk;
template <class T>
inline T* Singleton<T>::Instance()
{
if(NULL == _instance.get())
{
Lockdown::Nested ld(_lk);
if(NULL == _instance.get())
{
_instance.reset(new T);
}
}
return _instance.get();
}
//Class that will implement the singleton mode,
//must use the macro in it's delare file
#define DECLARE_SINGLETON_CLASS( type ) \
friend class auto_ptr< type >;\
friend class Singleton< type >;2. 多线程互斥
Lock.h
也可以使用BOOST库实现,使用mutex实现多线程互斥,在返回一个实例的判断之前锁定该线程。
#include <Windows.h>
// Instances of this class will be accessed by multiple threads.
class Lockdown {
public:
Lockdown()
{
m_Cnt = 0;
InitializeCriticalSection(&m_cs);
}
~Lockdown()
{
DeleteCriticalSection(&m_cs);
}
// IsGuarded is used for debugging
bool IsGuarded() const
{
return(m_Cnt > 0);
}
public:
class Nested {
public:
Nested(Lockdown& ld) : m_ld(ld) { m_ld.Guard(); };
~Nested() { m_ld.Unguard(); }
private:
Lockdown& m_ld;
};
private:
void Guard() { EnterCriticalSection(&m_cs); m_Cnt++; }
void Unguard() { m_Cnt--; LeaveCriticalSection(&m_cs); }
// Guard/Unguard can only be accessed by the nested CGuard class.
friend class Lockdown::Nested;
private:
CRITICAL_SECTION m_cs;
long m_Cnt; // # of EnterCriticalSection calls
};3. 测试代码
Singleton.cpp
#include <memory>
#include "Singleton.h"
#include <iostream>
using namespace std;
class TestSingleton
{
public:
void Run()
{
cout<<"I'm a singletoned class...haha"<<endl;
cout<<"This address is "<<this<<endl;
}
private:
TestSingleton(){}
virtual ~ TestSingleton(){}
DECLARE_SINGLETON_CLASS(TestSingleton);
};
int main()
{
TestSingleton *t = Singleton<TestSingleton>::Instance();
TestSingleton *p = Singleton<TestSingleton>::Instance();
cout<<"Address t="<<t<<endl;
cout<<"Address p="<<p<<endl;
t->Run();
p->Run();
system("pause");
return 0;
}