教面試官ReentrantLock源碼
945
2025-03-31
@TOC
零、前言
本章我們主要講解學(xué)習(xí)特殊類的設(shè)計(jì)方式
一、不能被拷貝
想要讓一個類禁止拷貝,只需讓該類不能調(diào)用拷貝構(gòu)造函數(shù)以及賦值運(yùn)算符重載即可
方式1:
C++98下,私有化拷貝構(gòu)造函數(shù)與賦值運(yùn)算符重載并且只聲明不定義
示例代碼:
class NoCopy { public: NoCopy() :_a(0) {} private: NoCopy(const NoCopy& oh);//只聲明不用實(shí)現(xiàn)(C98) NoCopy& operator=(const NoCopy& oh) ; int _a; };
解釋:
設(shè)置成私有:如果只聲明沒有設(shè)置成private,用戶自己如果在類外定義了,就可以不能禁止拷貝了
只聲明不定義:不定義是因?yàn)樵摵瘮?shù)根本不會調(diào)用,定義了其實(shí)也沒有什么意義
方式二:
C++11下,在拷貝構(gòu)造函數(shù)與賦值運(yùn)算符重載函數(shù)后跟上=delete
示例代碼:
class NoCopy { public: NoCopy() :_a(0) {} private: NoCopy(const NoCopy& oh)=delete;//C++11 NoCopy& operator=(const NoCopy& oh)=delete; int _a; };
注:C++11擴(kuò)展delete的用法,delete除了釋放new申請的資源外,如果在默認(rèn)成員函數(shù)后跟上=delete,表示讓編譯器刪除掉該默認(rèn)成員函數(shù),即不能被調(diào)用
示圖:
二、只能在堆上創(chuàng)建對象
方式1:
構(gòu)造函數(shù)私有化,棧上創(chuàng)建的對象銷毀調(diào)用不了析構(gòu)函數(shù)而報錯;給定特有的銷毀函數(shù),對堆上變量進(jìn)行銷毀
示例代碼:
class OnlyHeap { public: void Destory() { delete this;//類函數(shù)里調(diào)用delete cout << "delete" << endl; } private: ~OnlyHeap()//析構(gòu)函數(shù)私有化,棧上創(chuàng)建的對象銷毀不能調(diào)用會報錯 { cout << "~OnlyHeap" << endl; } int _a; };
解釋:
構(gòu)造函數(shù)私有化:對于棧上創(chuàng)建的對象銷毀調(diào)用不了析構(gòu)函數(shù)會報錯,也就是間接的不讓創(chuàng)建棧對象
給定特有的銷毀函數(shù):在類函數(shù)里可以訪問私有成員,進(jìn)行delete時能夠使用私有的析構(gòu)函數(shù)并進(jìn)行釋放對象
方式2:
私有化構(gòu)造函數(shù),拷貝構(gòu)造。防止別人調(diào)用拷貝在棧上生成對象;提供靜態(tài)的成員函數(shù),在該靜態(tài)成員函數(shù)中完成堆對象的創(chuàng)建
示例代碼:
class OnlyHeap { public: static OnlyHeap* ObjCreat()//提供對象創(chuàng)建的靜態(tài)成員方法 { cout << "new OnlyHeap" << endl; return new OnlyHeap; } private: OnlyHeap()//禁止直接調(diào)用構(gòu)造 :_a(0) { cout << "OnlyHeap" << endl; } OnlyHeap(const OnlyHeap& oh);//防止拷貝 OnlyHeap& operator=(const OnlyHeap& oh); int _a; };
解釋:
私有化構(gòu)造函數(shù)/拷貝構(gòu)造:防止別人調(diào)用拷貝在棧上生成對象
提供靜態(tài)創(chuàng)建對象函數(shù):在該靜態(tài)成員函數(shù)中完成堆對象的創(chuàng)建,類里的函數(shù)能夠調(diào)用私有化的構(gòu)造函數(shù)
注:一定是靜態(tài)的成員函數(shù),靜態(tài)成員函數(shù)不需要依賴對象進(jìn)行調(diào)用,普通的成員函數(shù)則不行
示圖:
三、只能在棧上創(chuàng)建對象
方式1:
顯示聲明并私有化operator new/operator delete函數(shù)
示例代碼:
class OnlyStack { public: OnlyStack() :_a(0) { cout << "Onlystack" << endl; } private: //顯示成私有化避免調(diào)用 void* operator new(size_t size); void operator delete(void* p); int _a; };
解釋:
顯示私有化:顯示是為了讓new的時候找到對象專屬的operator new函數(shù),私有化則是為了不讓operator new函數(shù)不被成功使用,避免調(diào)用
注:唯一的缺點(diǎn)是不能避免在靜態(tài)區(qū)創(chuàng)建對象
示圖:
方式2:
私有化構(gòu)造函數(shù),提供特定創(chuàng)建對象的靜態(tài)成員函數(shù)
示例代碼:
class OnlyStack { public: static OnlyStack ObjCreat() { return OnlyStack();//類里進(jìn)行調(diào)用構(gòu)造 } private: OnlyStack()//構(gòu)造私有化,避免new調(diào)用 :_a(0) { cout << "OnlyStack" << endl; } int _a; };
解釋:
私有化構(gòu)造函數(shù):new一個對象=調(diào)用類的構(gòu)造函數(shù)+operator new(),這里避免new調(diào)用創(chuàng)建對象
四、不能被繼承的類
方式1:
在C++98下,私有化構(gòu)造函數(shù),提供特定的創(chuàng)建靜態(tài)成員函數(shù)
示例:
class NonInherit { public: static NonInherit GetInstance() { return NonInherit(); } private: // 構(gòu)造函數(shù)私有 NonInherit() {} }; class Derive : NonInherit {};
解釋:
C++98 這種方式不夠直接,這里是可以繼承的,但是Derive不能創(chuàng)建對象,因?yàn)镈erive的構(gòu)造函數(shù)必須要調(diào)用父類NonInherit構(gòu)造,但是NonInherit的構(gòu)造函數(shù)私有了,私有在子類不可見,那么這里繼承不會報錯,繼承的子類創(chuàng)建對象會報錯
方式2:
final修飾類,表示該類不能被繼承
示例代碼:
class NoInherit final { }; class Derive : NoInherit {};
示圖:
五、只能創(chuàng)建一個對象
設(shè)計(jì)模式的概念:
設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)
使用設(shè)計(jì)模式的目的:
為了代碼可重用性、讓代碼更容易被他人理解、保證代碼可靠性;設(shè)計(jì)模式使代碼編寫真正工程化
單例模式:
一個類只能創(chuàng)建一個對象,即單例模式,該模式可以保證系統(tǒng)中該類只有一個實(shí)例,并提供一個訪問它的全局訪問點(diǎn),該實(shí)例被所有程序模塊共享
比如:
在某個服務(wù)器程序中,該服務(wù)器的配置信息存放在一個文件中,這些配置數(shù)據(jù)由一個單例對象統(tǒng)一讀取,然后服務(wù)進(jìn)程中的其他對象再通過這個單例對象獲取這些配置信息,這種方式簡化了在復(fù)雜環(huán)境下的配置管理
單例模式有兩種實(shí)現(xiàn)模式:
餓漢模式和懶漢模式
1、餓漢模式
當(dāng)程序啟動時就創(chuàng)建一個唯一的實(shí)例對象
示例代碼:
class Singleton { public: static Singleton& GetInstance()//獲取實(shí)例地址 { return _s; } vector
解釋:
類里面的成員變量只是聲明,而靜態(tài)成員對象需要在類外進(jìn)行定義,并且不能在.h文件中定義,如果多個.cpp文件包含該頭文件,那么則會報重復(fù)定義的錯誤
效果:
優(yōu)勢:
實(shí)現(xiàn)簡單
劣勢:
如果單例對象構(gòu)造十分耗時或者占用很多資源,比如加載插件啊, 初始化網(wǎng)絡(luò)連接啊,讀取文件啊等等,而有可能該對象程序運(yùn)行時不會用到,那么也要在程序一開始就進(jìn)行初始化,就會導(dǎo)致程序啟動時非常的緩慢
對于多個單例類的如果具有依賴關(guān)系的話,則無法進(jìn)行控制定義順序(靜態(tài)變量)
2、懶漢模式
懶漢模式則是需要的時候在第一次調(diào)用的時候進(jìn)行創(chuàng)建
示例代碼:
class Singleton { public: //提供獲取對象以及釋放對象的靜態(tài)方法 static Singleton& GetInstance() { //提高效率,避免多次鎖住及解鎖 if (_s == nullptr) { //保證線程安全 _m.lock();//鎖住 if (_s == nullptr) { _s = new Singleton; } _m.unlock();//解鎖 } return *_s; } static void DelInstance() { //提高效率,避免多次鎖住及解鎖 if (_s != nullptr) { //保證線程安全 _m.lock();//鎖住 if (_s != nullptr) { delete _s; _s = nullptr; } _m.unlock();//解鎖 } } vector
解釋:
對于懶漢模式需要注意的是要保證線程安全,當(dāng)多個進(jìn)行調(diào)用GetInstance()/DelInstance()時,可能多次進(jìn)行new和delete,可能造成數(shù)據(jù)的丟失
效果:
優(yōu)勢:
無啟動負(fù)載;可以自由控制多個單例類的定義順序
劣勢:
實(shí)現(xiàn)復(fù)雜
C++
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。