c++中的單例類模板的實(shí)現(xiàn)方法詳解
1、什么是單例模式
在架構(gòu)設(shè)計(jì)時(shí),某些類在整個(gè)系統(tǒng)生命周期中最多只能有一個(gè)對(duì)象存在 ( Single Instance )。如超市收銀系統(tǒng),其外觀主要由顯示器(1個(gè))、掃描槍(1個(gè))、收款箱(1個(gè))組成,在系統(tǒng)正常運(yùn)行期間這三部分都是唯一存在的;也就是說,顯示器、掃描槍、收款箱這三部分都應(yīng)該有各自的類,并且每個(gè)類只能唯一地實(shí)例化一個(gè)對(duì)象,基于這種模式的程序設(shè)計(jì),稱為單例模式。
?。?!單例模式只能創(chuàng)建一個(gè)對(duì)象,且該對(duì)象的生命周期伴隨系統(tǒng)的整個(gè)運(yùn)行期間。
2、怎么實(shí)現(xiàn)單例模式
思考:如何定義一個(gè)類,使得這個(gè)類最多只能創(chuàng)建一個(gè)對(duì)象?
分析:因?yàn)閷?duì)象是由構(gòu)造函數(shù)創(chuàng)建的,所以我們應(yīng)該將問題鎖定在構(gòu)造函數(shù)上;又因?yàn)橹荒軇?chuàng)建一個(gè)對(duì)象,這就意味著只能調(diào)用一次構(gòu)造函數(shù);顯然將構(gòu)造函數(shù)的訪問權(quán)限設(shè)置為 public 不合適,所以,構(gòu)造函數(shù)的訪問權(quán)限只能是 private。然后,定義一個(gè)私有的靜態(tài)成員 c_instance = NULL 和 公有的靜態(tài)成員函數(shù),通過 c_instance 來判斷是否創(chuàng)建對(duì)象。(這個(gè)為什么要使用 靜態(tài)成員呢?因?yàn)闃?gòu)造函數(shù)是私有的,在類的外部無法創(chuàng)建對(duì)象,只能通過類名調(diào)用靜態(tài)成員,而靜態(tài)成員函數(shù)只能調(diào)用靜態(tài)成員變量)
上述分析過程可簡(jiǎn)化為:
?。?)將構(gòu)造函數(shù)的訪問屬性設(shè)置為 private;
?。?)定義私有的靜態(tài)成員屬性 instance 并初始化為 NULL;
?。?)當(dāng)需要使用對(duì)象時(shí),訪問 instance 的值;
1)空值:創(chuàng)建對(duì)象,并用 instance 標(biāo)記;
2)非空值:返回 instance 標(biāo)記的對(duì)象;
單例模式實(shí)現(xiàn)
#include <iostream>
#include <string>
using namespace std;
class SObject
{
static SObject* c_instance; // 定義標(biāo)識(shí)符指針;
/* 不需用拷貝和賦值,在單例模式中,始終只有一個(gè)對(duì)象 */
SObject(const SObject&);
SObject& operator= (const SObject&);
SObject() // 私有的構(gòu)造函數(shù)
{
}
public:
static SObject* GetInstance(); // 創(chuàng)建對(duì)象的入口
void print()
{
cout << "this = " << this << endl;
}
};
SObject* SObject::c_instance = NULL; // 靜態(tài)成員類內(nèi)聲明,類外定義
SObject* SObject::GetInstance() // 單例模式的關(guān)鍵
{
if( c_instance == NULL )
{
c_instance = new SObject();
}
return c_instance;
}
int main()
{
SObject* s = SObject::GetInstance();
SObject* s1 = SObject::GetInstance();
SObject* s2 = SObject::GetInstance();
s->print(); // this = 0x940a008
s1->print(); // this = 0x940a008
s2->print(); // this = 0x940a008
return 0;
}
// 注:?jiǎn)卫J街?,?duì)象的生命周期存在整個(gè)系統(tǒng)運(yùn)行過程中,所以是絕對(duì)不釋放的;
· 其實(shí),在上述的單例模式實(shí)現(xiàn)案列中,有一部分代碼(分析過程中第2、3步)與類本身沒有任何關(guān)系,既然是這樣,我們就把這部分單獨(dú)提取出來處理。
問題所在:需要使用單例模式時(shí),必須在每個(gè)類中定義 靜態(tài)成員變量 c_instance 和 靜態(tài)成員函數(shù) GetInstance();當(dāng)有多個(gè)類都需要使用單例模式時(shí),這樣的實(shí)現(xiàn)方式明顯的很冗余,為了能夠代碼復(fù)用,我們可以 將這兩部分抽象成一個(gè)新類(做成類模板,聲明為其它類的友元類,這樣與之前的效果一樣)。
基于類模板的單例模式實(shí)現(xiàn)
// 對(duì)上個(gè)單例模式實(shí)現(xiàn)代碼的改進(jìn)
// singleton.hpp 單例模式代碼
#ifndef SINGLETON_H
#define SINGLETON_H
template
< typename T >
class Singleton
{
static T* c_instance;
public:
static T* GetInstance();
};
template
< typename T >
T* Singleton<T>::c_instance = NULL;
template
< typename T >
T* Singleton<T>::GetInstance()
{
if( c_instance == NULL )
{
c_instance = new T();
}
return c_instance;
}
#endif
// main.cpp 測(cè)試文件
#include <iostream>
#include <string>
#include "singleton.hpp"
using namespace std;
class SObject
{
friend class Singleton<SObject>; // 當(dāng)前類需要使用單例模式
SObject(const SObject&);
SObject& operator= (const SObject&);
SObject()
{
}
public:
void print()
{
cout << "this = " << this << endl;
}
};
int main()
{
SObject* s = Singleton<SObject>::GetInstance();
SObject* s1 = Singleton<SObject>::GetInstance();
SObject* s2 = Singleton<SObject>::GetInstance();
s->print(); // 0xe63c20
s1->print(); // 0xe63c20
s2->print(); // 0xe63c20
return 0;
}
在今后工作中,如果一個(gè)類(SObject)要使用單例模式(Singleton 單例模式的類模板),只需三步驟:
?。?)類(SObject)的構(gòu)造函數(shù)必須私有化;同時(shí),拷貝構(gòu)造函數(shù)、重載=操作符 也私有化;
(2)將單例模式的類模板聲明為這個(gè)類的友元類; friend class Singleton<SObject>;
?。?)通過 單例模式類模板中 SObject* s = Singleton<SObject>::GetInstance(); 創(chuàng)建對(duì)象。
到此這篇關(guān)于c++中的單例類模板的實(shí)現(xiàn)方法詳解的文章就介紹到這了,更多相關(guān)c++ 單例類模板內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ 實(shí)現(xiàn)LRU 與 LFU 的緩存算法
設(shè)計(jì)和實(shí)現(xiàn)一個(gè)LRU 緩存機(jī)制。其支持獲取數(shù)據(jù) get 和 寫入數(shù)據(jù) put,設(shè)計(jì)并實(shí)現(xiàn)最少訪問頻率(LFU)緩存的數(shù)據(jù)結(jié)構(gòu)。LFU的每個(gè)數(shù)據(jù)塊都有一個(gè)引用計(jì)數(shù),所有數(shù)據(jù)塊按照引用計(jì)數(shù)排序,具有相同引用計(jì)數(shù)的數(shù)據(jù)塊則按照時(shí)間進(jìn)行排序。其支持get 和 put,具體了解請(qǐng)看下文2021-09-09
VC++ loadlibrary()加載三方dll失敗, 返回錯(cuò)誤碼:126的解決方法
今天在編寫VC++ loadlibrary()加載三方dll是總是失敗,并且返回錯(cuò)誤碼:126,這里就為大家分享一下具體的解決方法2021-03-03
Visual Studio Code (vscode) 配置 C / C++ 環(huán)境的流程
這篇文章主要介紹了Visual Studio Code (vscode) 配置 C / C++ 環(huán)境的流程,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09
C++?OpenCV紅綠燈檢測(cè)Demo實(shí)現(xiàn)詳解
OpenCV(Open Source Computer Vision Library)是開源的計(jì)算機(jī)視覺和機(jī)器學(xué)習(xí)庫(kù),提供了C++、 C、 Python、 Java接口,并支持Windows、 Linux、 Android、 Mac OS平臺(tái),下面這篇文章主要給大家介紹了關(guān)于C++?OpenCV紅綠燈檢測(cè)Demo實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2022-11-11
C語言數(shù)組和指針,內(nèi)存之間的關(guān)系
這篇文章主要介紹了C語言數(shù)組和指針,內(nèi)存之間的關(guān)系,首先論證一維數(shù)組和一級(jí)指針之前的關(guān)系,我們常常使用一級(jí)指針指針的方式訪問一維數(shù)組,只有對(duì)內(nèi)存的理解到位才能理解它們直接的關(guān)系。需要的小伙伴可以參考一下2022-02-02

