歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

利用C++對象確定性析構的原則來解析單例模式

設計模式思想是可重用,我們在編程的過程中,或多或少都會接觸到設計模式,只是,有時,我們相交卻未相識罷了,那麼我們今天來講解單例模式,並且附之一個C++的編程技巧。

我們知道單例模式在實際開發過程中是很有用的,單例模式的特征我們可能都知道:

1、一個類只有一個實例

2、提供一個全局訪問點

3、禁止拷貝

我們來逐個分析:

1、如果要實現只有一個實例,我們需要做的事情:

a、將構造函數聲明為私有

2、提供一個全局訪問點

a、類中創建靜態成員函數

3、禁止拷貝

a、拷貝構造函數聲明為私有,並且不提供實現

b、將賦值運算符聲明為私有

我們在書寫單例類的時候如何測試呢?兩個方法:


1、實例化多個對象,看調用了幾次構造函數,如果只調用一次,說明只創建一個實例

2、單步跟蹤,查看對象的地址,是否一樣,一樣則為一個對象

------------我是分割線-------------

在學習C++的過程中,我們很早就接觸到了構造函數和析構函數,這兩個函數都是系統自動調用的,縱使我們不聲明構造函數和析構函數,系統也會替我們生成。

那麼在C++編程就有確定性析構,也就是是說,無論怎麼樣,只要創建了對象,系統就會調用析構函數,那麼如果我們在類中嵌套一個類,並且在外面類中聲明一個嵌套類對象,那麼,嵌套類對象的析構函數是一定調用的,我們可不可以在嵌套類的析構函數裡面做點東西呢?

我們的方法是:

在單例類Singleton中定義為Garbo的私有內嵌類,以防該類被在其他地方濫用。
程序運行結束時,系統會調用Singleton的靜態成員Garbo的析構函數,該析構函數會***單例的唯一實例
使用這種方法釋放單例對象的特征:
1、在單例類內部定義專有的嵌套類;
2、在單例類內定義私有的專門用於釋放的靜態成員;
3、利用程序在結束時析構全局變量的特性,選擇最終的釋放時機;
4、使用單例的代碼不需要任何操作,不必關心對象的釋放。

C++ Primer Plus 第6版 中文版 清晰有書簽PDF+源代碼 http://www.linuxidc.com/Linux/2014-05/101227.htm

讀C++ Primer 之構造函數陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm

讀C++ Primer 之智能指針 http://www.linuxidc.com/Linux/2011-08/40177.htm

讀C++ Primer 之句柄類 http://www.linuxidc.com/Linux/2011-08/40175.htm

C++11 獲取系統時間庫函數 time since epoch http://www.linuxidc.com/Linux/2014-03/97446.htm

C++11中正則表達式測試 http://www.linuxidc.com/Linux/2012-08/69086.htm

代碼如下:

------------我是分割線-------------

# include <iostream>

using namespace std; 

//當static Garbo garbo_ 對象的生命周期結束時,會調用嵌套類Garbo的析構

//函數,同時也instance_的銷毀

//利用了對象確定性析構的原則

 

//施加約束,只有一個實例,只需要將構造函數聲明為私有的

//需要一個全局的訪問點,

class Singleton

{

public:

    static Singleton* GetInstance()

    {

        if(NULL == instance_)

        {

            instance_ = new Singleton;

        }

       

        return instance_;

    }

    ~Singleton()

    {

        cout << "~Singleton ..." << endl;

    }

 

    /*這種方法也可以釋放資源,是笨方法

    static void Free()

    {

        if(NULL != instance_ )

        {

            delete instance_;

        }

    }

    */

        //嵌套類

    class Garbo

    {

    public:

        ~Garbo()

        {

            if(Singleton::instance_ != NULL)

            {

                delete instance_; 

            }

        }

    };

 

private:

    //拷貝構造函數聲明為私有,就可以禁止拷貝,並且不提供實現

    Singleton(const Singleton&  other);

    //也要禁止賦值,將賦值運算符聲明為私有

    Singleton&  operator=(const Singleton&  other);

 

    Singleton()

    {

        cout << "Singleton ..." << endl;

    }

    //僅僅是聲明,如果定義,需要放在類外面

    static Singleton*  instance_; 

        //創建garbo對象,是聲明

    static Garbo garbo_; 

    //利用了對象確定性析構的原則

 

};

//因為Garbo是嵌套類,所以前面要加SIngleton

Singleton::Garbo Singleton::garbo_;  //前面的static就不需要了

Singleton*  Singleton::instance_;

 

int main(void)

{

    //不管GetInstance調用多少次,都返回是同一個實例

    Singleton*  s = Singleton::GetInstance();

    Singleton*  s1 = Singleton::GetInstance();

 

    //Singleton s3(*s);    error  禁止拷貝

    //Singleton s3 = *s;  error  禁止賦值

    //構造幾個實例,就調用幾個構造函數,所以只調用一次構造函數

 

    //Singleton::Free();  對資源進行釋放,此為笨方法

 

    return 0;

}


------------我是分割線-------------

PS:

1、上述方法不是線程安全的

2、還可以利用智能指針auto_ptr實現,我們後期再論

3、除了嵌套類,上面還給出了笨方法,大家挖掘

------------我是分割線-------------

Copyright © Linux教程網 All Rights Reserved