1. 程式人生 > >C++可繼承的單例基類模板

C++可繼承的單例基類模板

遞歸 構造函數 single reat exce efault val 參考資料 重點

目錄

  • 一、介紹
  • 二、代碼
  • 三、關鍵處
  • 四、使用限制
  • 五、參考資料

一、介紹

最近在寫一個項目,其中用到好幾個單例,類本身的設計不是很復雜,但是如果每個都寫一遍單例又覺得有點冗余;所以查資料寫了一個單例基類模板,只要一個類繼承這個基類並且以自身作為模板參數就可以實現一個單例;關於單例本身的介紹在這裏不重點介紹。
特點:

  • RAII,使用 std::shared_ptr來管理資源
  • 線程安全,加了鎖
  • 以上特性基於C++11

二、代碼

// bridf: a singleton base class offering an easy way to create singleton
#include <memory> // shard_ptr
#include <mutex>
#include <iostream>
template<typename T>
class Singleton{
    typedef std::shared_ptr<T> Ptr;
protected:
    Singleton() noexcept=default;
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
    virtual ~Singleton() = default; 
    static Ptr instance_ptr;
    static std::mutex singleton_mutex;
public:

    static Ptr get_instance() noexcept(std::is_nothrow_constructible<T>::value)
    {
        if(instance_ptr==nullptr){
           std::lock_guard<std::mutex> lk(singleton_mutex);
           if(instance_ptr==nullptr){
                instance_ptr = std::shared_ptr<T>(new T());
           }
        }
        return instance_ptr;

    }
};
template <typename T>
std::shared_ptr<T> Singleton<T>::instance_ptr=nullptr;

template <typename T>
std::mutex Singleton<T>::singleton_mutex;


/********************************************/
// 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>;
   int value;
public:

   void info(){
       std::cout<<"value: \n";
       std::cout<<value<<std::endl;
   }
   void set_value(int i){
       value  = i;
   }
   int get_value(){
       return value;
   }
private:
   DerivedSingle():value(0){}
   DerivedSingle(const DerivedSingle&)=delete;
   DerivedSingle& operator =(const DerivedSingle&)= delete;
};

int main(int argc, char* argv[]){
    std::shared_ptr<DerivedSingle> instance  = DerivedSingle::get_instance();
    instance->info();
    instance->set_value(1);
    std::shared_ptr<DerivedSingle> instance2 = DerivedSingle::get_instance();
    instance2->info();
    return 0;
}

以上代碼放在了 我的github中: https://github.com/sunchaothu/AdvancedCpp/tree/master/singleton

三、關鍵處

  • 子類需要把自己作為模板參數,如 class DerivedSingle:public Singleton<DerivedSingle>;
    這裏用到的是CRTP(Curiously recurring template pattern) 遞歸循環模板模式
  • 在子類中需要把基類 Singleton 聲明為友元;這樣才能訪問私有構造函數

四、使用限制

繼承了這個類的代碼不可以作為基類再被繼承。

五、參考資料

以上代碼參考了以下鏈接;如果有紕漏之處,還請指正,以免誤人子弟!

  1. https://stackoverflow.com/questions/34519073/inherit-singleton?r=SearchResults
  2. https://www.cnblogs.com/lidabo/p/3949226.html

C++可繼承的單例基類模板