可以繼承的C++ Singleton基類
單例模式(Singleton Pattern)是設計模式中的一種,它用來保證系統中最多只能存在一個它的實例,其做法是由類自身來創建和持有它的對象實例,把對實例的創建權和管理權都控制在自己手中,以便控制實例數目。
關于如何在C++中實現單例模式的討論已經太多了,我只是簡單介紹一下可以繼承的單例類。
首先介紹一下通常所見的單例類的寫法,不妨設這個類叫做Singleton。
Singleton.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
#ifndef _SINGLETON_H_
#define _SINGLETON_H_
#include <memory>
class Singleton
{
public:
static Singleton& GetInstance();
private:
Singleton();
~Singleton();
// Use auto_ptr to make sure that the allocated memory for instance
// will be released when program exits (after main() ends).
static std::auto_ptr<Singleton> s_instance;
friend class std::auto_ptr<Singleton>;
Singleton(const Singleton&);
Singleton& operator =(const Singleton&);
};
#endif
Singleton.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
#include "Singleton.h"
#include <iostream>
#include <boost/thread.hpp>
using namespace std;
using namespace boost;
auto_ptr<Singleton> Singleton::s_instance;
Singleton::Singleton()
{
cout << "Construct Singleton" << endl;
}
Singleton::~Singleton()
{
cout << "Destruct Singleton" << endl;
}
Singleton& Singleton::GetInstance()
{
static mutex s_mutex;
if (s_instance.get() == NULL)
{
mutex::scoped_lock lock(s_mutex);
if (s_instance.get() == NULL)
{
s_instance.reset(new Singleton());
}
// 'lock' will be destructed now. 's_mutex' will be unlocked.
}
return *s_instance;
}
這個類寫的也不完美啦,比如雙重判定也會有失效的時候,不過湊合用吧,哈哈。不過話說boost庫里也有singleton,我為什么要自己寫個呢,無奈地飄過。
廢話不多說了,上面的單例類基本上解決了多線程安全問題、實例內存自動釋放問題,算是一段可以使用的程序。不過如果系統中有大量單例類(這時候也得好好考慮一下design有沒有問題),每個都要這么寫一番豈不是很麻煩?要是可以寫一個單例基類,以后再創造單例類的時候直接繼承一下多方便啊。不過很明顯的問題就在那個static對象指針,這個用來保存唯一實例的靜態變量如果定義在基類里面,那所有的子類都只能用這同一個變量來保存它們各自的實例了,社會主義國家總得讓每個子類都過上溫飽生活吧!
以前的時候我還真不知道該怎么解決這個問題,但05年用了WTL(Windows Template Library)之后,我才意識到模板類可以幫助我(話說我真的是自己想到的,雖然現在搜一下能搜到一大堆)。這里要用的還不是普通的模板類,而是像ATL、WTL里面那樣把要定義的類自身放入模板參數中,形如class MyClass : public Base<MyClass> { };
。這樣做有很多優點啦,最顯著的比如不需要虛表(節省內存哦)、多態函數的調用在編譯時就確定了(既加快了運行速度,也有利于編譯器對代碼進行優化)。
不妨把這個單例基類叫做ISingleton吧,看起來好像是個interface呢。代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
#ifndef _ISingleton_H_
#define _ISingleton_H_
#include <memory>
#include <boost/thread.hpp>
template <typename T>
class ISingleton
{
public:
static T& GetInstance()
{
static boost::mutex s_mutex;
if (s_instance.get() == NULL)
{
boost::mutex::scoped_lock lock(s_mutex);
if (s_instance.get() == NULL)
{
s_instance.reset(new T());
}
// 'lock' will be destructed now. 's_mutex' will be unlocked.
}
return *s_instance;
}
protected:
ISingleton() { }
~ISingleton() { }
// Use auto_ptr to make sure that the allocated memory for instance
// will be released when program exits (after main() ends).
static std::auto_ptr<T> s_instance;
private:
ISingleton(const Singleton&);
ISingleton& operator =(const ISingleton&);
};
template <typename T>
std::auto_ptr<T> ISingleton<T>::s_instance;
#endif
要利用ISingleton創建一個自己的單例類,比如MySingleton,可以使用如下的代碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
#include "Singleton.h"
#include "ISingleton.h"
#include <iostream>
using namespace std;
class MySingleton : public ISingleton<MySingleton>
{
public:
// blah blah
private:
MySingleton()
{
cout << "Construct MySingleton" << endl;
}
~MySingleton()
{
cout << "Destruct MySingleton" << endl;
}
friend ISingleton<MySingleton>;
friend class auto_ptr<MySingleton>;
MySingleton(const MySingleton&);
MySingleton& operator =(const MySingleton&);
};
最最重要的,千萬不要忘了把MySingleton的構造和析構函數弄成private的,還要添加兩個友元。有人說ISingleton和MySingleton的析構函數都要加virtual,我倒是覺得沒有必要呢,你說呢?另外要注意,MySingleton不能被繼承哦。
RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成