一、介紹
最近在寫一個項目,其中用到好幾個單例,類本身的設計不是很復雜,但是如果每個都寫一遍單例又覺得有點冗余;所以查資料寫了一個單例基類模板,只要一個類繼承這個基類並且以自身作為模板參數就可以實現一個單例;關於單例本身的介紹在這里不重點介紹,感興趣的可以看一下我的另外一篇博文(https://www.cnblogs.com/sunchaothu/p/10389842.html),寫的非常詳細,把各種單例實現方法總結了一遍,並且給出技術細節分析。
特點:
- 線程安全,使用 staic local,保證線程安全 (C++11)
- 可以繼承的模板,更加方便的實現單例
二、代碼
// author: sunchaothu
// brief: a singleton base class offering an easy way to create singleton
#include <iostream>
template<typename T>
class Singleton{
public:
static T& get_instance() noexcept(std::is_nothrow_constructible<T>::value){
static T instance;
return instance;
}
virtual ~Singleton() noexcept{
std::cout<<"destructor called!"<<std::endl;
}
Singleton(const Singleton&)=delete;
Singleton& operator =(const Singleton&)=delete;
protected:
Singleton(){
std::cout<<"constructor called!"<<std::endl;
}
};
/********************************************/
// Example:
// 1.friend class declaration is requiered!
// 2.constructor should be private
class DerivedSingle:public Singleton<DerivedSingle>{
// !!!! attention!!!
// needs to be friend in order to
// access the private constructor/destructor
friend class Singleton<DerivedSingle>;
public:
DerivedSingle(const DerivedSingle&)=delete;
DerivedSingle& operator =(const DerivedSingle&)= delete;
private:
DerivedSingle()=default;
};
int main(int argc, char* argv[]){
DerivedSingle& instance1 = DerivedSingle::get_instance();
DerivedSingle& instance2 = DerivedSingle::get_instance();
return 0;
}
以上代碼放在了 我的github中: https://github.com/sunchaothu/AdvancedCpp/tree/master/singleton
三、關鍵處
- 子類需要把自己作為模板參數,如
class DerivedSingle:public Singleton<DerivedSingle>;
這里用到的是CRTP(Curiously recurring template pattern) 奇異循環模板模式 - 在子類中需要把基類
Singleton
聲明為友元;這樣才能訪問私有構造函數(這個鏈接里還提供了不需要聲明為友元的實現) - 這個使用了局部靜態變量保證了線程安全,成為 Magic Static。
四、使用限制
繼承了這個類的代碼不可以作為基類再被繼承。
五、參考資料
以上代碼參考了以下鏈接;如果有紕漏之處,還請指正,以免誤人子弟!