<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    可以繼承的C++ Singleton基類

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    單例模式(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中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全