c++ 單例模式 對全局變量的替代


前段時間要實習一個充值接口,創建了一個類(就叫類A好了),這個類A要和另外3個類進行交互,3個類對類A修改的數據是對其他類可見的。這種情況我想到了3個方法:

1.static 靜態成員,靜態成員為該類的所有實例所共享,3個類中各自創建一個類A的對象,它們對靜態成員的修改對其他類可見。

2.全局變量,類A的頭文件中添加   extern  classA  g_classA; 源文件中添加 classA g_classA;   3個類中添加頭文件后直接通過g_classA   //這種不推薦

3.單例模式

 

使用單例模式替代全局變量,3個類對類A的函數訪問都是對類A的唯一實例的數據訪問,修改對其他類自然可見了。單例模式是使用全局變量的常見替代方法。

 

下面是轉自一位前輩的單例實現模式的總結,第三種實現實在太精彩了,只能用"nice catch"來形容!

——————————華麗的分割線——————————

轉自:http://lwzy-crack.blog.163.com/blog/static/9527204220091068526135/

C++中的單例模式 

單例模式很有用,使用單例模式,保證一個類僅有一個實例,並提供一個訪問它的全局訪問點,該實例被所有程序模塊共享。
但是在程序的開發過程中我們總是遇到一些問題,而這些問題主要集中在單例類的消毀過程中,普通使用的單例模式的類如下:
class Singleton:
{
    // 其它成員
public:
    static Singleton * GetInstance()
    {
        if (m_pInstance == NULL)
            m_pInstance = new Singleton();
        return m_pInstance;
    }
 
private:
    Singleton(){};
    static Singleton * m_pInstance;
}

可是這個類在什么時候調用它的析構函數呢,我們怎么消毀它。提供一個公用的destroy函數來進行它的消毀嗎,這很不美觀。最后我就在網上找到了如果下的代碼處理了這個問題:
class Singleton:
{
    // 其它成員
public:
    static Singleton * GetInstance(){...}
private:
    Singleton(){};
    static Singleton * m_pInstance;
 
    class CGarbo // 它的唯一工作就是在析構函數中刪除Singleton的實例
    {
    public:
        ~CGarbo(){
            if (Singleton::m_pInstance)
                delete Singleton::m_pInstance;
        }
    };
 
    static CGarbo Garbo; // 定義一個靜態成員,在程序結束時,系統會調用它的析構函數
}

這是非常好的方法,靜態成員對象 Garbo 在析構時會自動的消毀單例,我們不用再擔心這個問題了。

但是添加一個類的靜態對象,總是讓人不太滿意,所以有人用如下方法來重現實現單例和解決它相應的問題,代碼如下:
class Singleton:
{
    // 其它成員
public:
    static Singleton &GetInstance(){
        static Singleton instance;
        return instance;
    }
 
private:
    Singleton(){};
}
使用局部靜態變量,非常強大的方法,完全實現了單例的特性,而且代碼量更少,也不用擔心單例消毀的問題。
在后期的項目中我全使用了這種方法,可是在項目的開發過程中還是出現了問題,當如下方法使用單例時問題來了,
Singleton singletion = Singleto::GetInstance();
這么做就產生了一個類拷貝的問題,這就為背了單例的特性。
產生這個問題的原因在於,編譯器會為類生成一個默認的構造函數,來支持類的拷貝。
最后沒有辦法,我們要禁止類拷貝和類賦值,禁止程序員用這種方式來使用單例,當時領導的意思是GetInstance()函數返回一個指針而不是返回一個引用,函數代碼改為如下:
    static Singleton *GetInstance(){
        static Singleton instance;
        return &instance;
    }

可我總是感覺不好,為什么不讓編譯器不這么干呢。這時我才想起可以顯式的聲明類拷貝的構造函數,和重載=操作符,新的單例類如下:

class Singleton:
{
    // 其它成員
public:
    static Singleton &GetInstance(){
        static Singleton instance;
        return instance;
    }
 
private:
    Singleton(){};

    Singleton(const Singleton&);
    Singleton & operate = (const Singleton&);
}
關於Singleton(const Singleton&);和Singleton & operate = (const Singleton&);函數,我們要聲明成私用的,並且只聲明不實現。這樣子后如果用上面的方式來使用單例時,不管是在友元類中還是其它的,編譯器都是報錯。
不知道這樣的單例類是否還會有問題,但在程序中這樣子使用已經基本沒有問題了。

 

——————————華麗的分割線——————————

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM