歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 利用C++對象確定性析構的原則來解析單例模式

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

日期:2017/3/1 9:43:40   编辑:Linux編程

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