国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【C++】特殊類設(shè)計(jì)(單例模式)

這篇具有很好參考價(jià)值的文章主要介紹了【C++】特殊類設(shè)計(jì)(單例模式)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一、設(shè)計(jì)模式概念

設(shè)計(jì)模式是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。
使用設(shè)計(jì)模式的目的:為了代碼可重用性、讓代碼更容易被他人理解、保證代碼可靠性。
根本原因是為了代碼復(fù)用,增加可維護(hù)性。

設(shè)計(jì)模式的例子:迭代器模式

二、設(shè)計(jì)一個(gè)不能被拷貝的類

拷貝一共就只有兩個(gè)場景,一個(gè)是拷貝構(gòu)造,一個(gè)是賦值運(yùn)算符重載。所以我們想要設(shè)計(jì)出一個(gè)不能被拷貝的類只需要讓外部無法調(diào)用這兩個(gè)函數(shù)即可。

在C++98中,我們的方法是將拷貝構(gòu)造和賦值運(yùn)算符重載只聲明不定義并且將權(quán)限設(shè)置為私有。

class anti_copy
{
public:
	anti_copy()
	{}
private:
	anti_copy(const anti_copy& ac);
	anti_copy& operator=(const anti_copy& ac);
};

設(shè)計(jì)原因:
1?? 私有:如果聲明成共有,那么就可以在類外面實(shí)現(xiàn)定義。
2?? 只聲明不定義:因?yàn)槿绻宦暶骶幾g器會(huì)默認(rèn)生成這兩個(gè)的默認(rèn)成員函數(shù)。而不定義是因?yàn)樵摵瘮?shù)不會(huì)被調(diào)用,就不用寫了,這樣編譯的時(shí)候就會(huì)出現(xiàn)鏈接錯(cuò)誤。

而在C++11中引入了關(guān)鍵字——delete。
如果在默認(rèn)成員函數(shù)后跟上=delete,表示讓編譯器刪除掉該默認(rèn)成員函數(shù)。即使權(quán)限是共有也無法調(diào)用已刪除的函數(shù)。

class anti_copy
{
public:
	anti_copy()
	{}
	anti_copy(const anti_copy& ac) = delete;
	anti_copy& operator=(const anti_copy& ac) = delete;
private:
};

三、設(shè)計(jì)一個(gè)只能在堆上創(chuàng)建對(duì)象的類

3.1 私有構(gòu)造

首先要把構(gòu)造函數(shù)給私有,不然這個(gè)類就可以在任意位置被創(chuàng)建。而構(gòu)造函數(shù)被私有了以后我們?cè)趺磩?chuàng)建對(duì)象呢?
我們可以在定義一個(gè)成員函數(shù),讓這個(gè)函數(shù)在堆上申請(qǐng)空間,但我們知道必須現(xiàn)有對(duì)象才能調(diào)用成員函數(shù)。所以我們就把這個(gè)函數(shù)設(shè)置成靜態(tài)成員函數(shù)。

class OnlyHeap
{
public:
	static OnlyHeap* GetObj()
	{
		return new OnlyHeap;
	}
private:
	OnlyHeap()
	{}
};

但是這樣也不完全對(duì),如果我們這么寫

class OnlyHeap
{
public:
	static OnlyHeap* GetObj()
	{
		return new OnlyHeap;
	}
private:
	OnlyHeap()
	{}
};

int main()
{
	OnlyHeap* hp1 = OnlyHeap::GetObj();
	OnlyHeap hp2(*hp1);
	return 0;
}

這里的hp2就是棧上的對(duì)象。所以我們也要把拷貝構(gòu)造給封住。

class OnlyHeap
{
public:
	static OnlyHeap* GetObj()
	{
		return new OnlyHeap;
	}

	OnlyHeap(const OnlyHeap& hp) = delete;
private:
	OnlyHeap()
	{}
};

3.2 私有析構(gòu)

class OnlyHeap
{
public:
	OnlyHeap()
	{}

	OnlyHeap(const OnlyHeap& hp) = delete;
private:
	~OnlyHeap()
	{}
};

int main()
{
	OnlyHeap hp1;// error
	OnlyHeap* hp2 = new OnlyHeap;
	return 0;
}

這里的hp1就不能創(chuàng)建成功,因?yàn)閷?duì)象銷毀的時(shí)候會(huì)調(diào)用析構(gòu)函數(shù),但是這里的析構(gòu)是私有的,所以該對(duì)象無法調(diào)用。

但是我們要銷毀hp2該怎么辦呢?
我們可以定義一個(gè)成員函數(shù)顯示調(diào)用析構(gòu)函數(shù)。

class OnlyHeap
{
public:
	OnlyHeap()
	{}

	OnlyHeap(const OnlyHeap& hp) = delete;

	void Destroy()
	{
		this->~OnlyHeap();
	}
private:
	~OnlyHeap()
	{}
};

int main()
{
	OnlyHeap* hp2 = new OnlyHeap;
	hp2->Destroy();
	return 0;
}

四、設(shè)計(jì)一個(gè)只能在棧上創(chuàng)建對(duì)象的類

為了不讓這個(gè)類隨便定義出對(duì)象,首先要把構(gòu)造函數(shù)私有。然后跟上面只能在堆上創(chuàng)建對(duì)象的方法相似,定義出一個(gè)靜態(tài)成員函數(shù)返回棧上創(chuàng)建的對(duì)象。

class StackOnly
{
public:
	static StackOnly GetObj()
	{
		return StackOnly();
	}
private:
	StackOnly()
	{}
};

int main()
{
	StackOnly hp = StackOnly::GetObj();
	return 0;
}

但是這里有一個(gè)問題,無法防止創(chuàng)建靜態(tài)對(duì)象:

static StackOnly hp2 = StackOnly::GetObj();

五、設(shè)計(jì)不能被繼承的類

在C++98,為了不讓子類繼承,我們可以把構(gòu)造函數(shù)私有化,因?yàn)樽宇愋枰日{(diào)用父類的構(gòu)造函數(shù)初始化父類的那一部分成員。

class NoInherit
{
public:
private:
	NoInherit()
	{}
};

而在C++11中引入的新的關(guān)鍵字final,被final關(guān)鍵字修飾的類不能被繼承。

class NoInherit final
{
public:
private:
};

六、單例模式????

一個(gè)類只能創(chuàng)建一個(gè)對(duì)象,即單例模式,該模式可以保證系統(tǒng)中該類只有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn),該實(shí)例被所有程序模塊共享。

單例模式的特點(diǎn)就是全局只有一個(gè)唯一對(duì)象。

6.1 餓漢模式

怎么能做到全局只是用一個(gè)對(duì)象呢,比方說我們現(xiàn)在想要實(shí)現(xiàn)一個(gè)英漢字典,首先我們要把構(gòu)造函數(shù)私有,不然無法阻止創(chuàng)建對(duì)象。然后我們可以在類里面定義一個(gè)自己類型的靜態(tài)成員變量,作用域是全局的。因?yàn)閷?duì)比定義在外邊的靜態(tài)成員變量,內(nèi)部的可以調(diào)用構(gòu)造函數(shù)。
這里要注意把拷貝也要封住。

class Singleton
{
public:
	static Singleton& GetObj()
	{
		return _s;
	}

	void insert(const std::string& s1, const std::string& s2)
	{
		_dict[s1] = s2;
	}

	void Print()
	{
		for (auto& e : _dict)
		{
			cout << e.first << "->" << e.second << endl;
		}
	}

	// 防拷貝
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
private:
	Singleton()
	{}

	std::map<std::string, std::string> _dict;
private:
	static Singleton _s;// 聲明
};

Singleton Singleton::_s;// 定義

int main()
{
	Singleton::GetObj().insert("corn", "玉米");

	Singleton& dic1 = Singleton::GetObj();
	dic1.insert("apple", "蘋果");
	dic1.insert("banana", "香蕉");

	Singleton& dic2 = Singleton::GetObj();
	dic2.insert("pear", "梨");

	dic2.Print();
	return 0;
}

【C++】特殊類設(shè)計(jì)(單例模式)
餓漢模式有什么特點(diǎn)呢?

它會(huì)在一開始(main之前)就創(chuàng)建對(duì)象。

餓漢模式有什么缺點(diǎn)呢?

1?? 如果單例對(duì)象構(gòu)造十分耗時(shí)或者占用很多資源,比如加載插件啊, 初始化網(wǎng)絡(luò)連接啊,讀取文件啊等等,而有可能該對(duì)象程序運(yùn)行時(shí)不會(huì)用到,那么也要在程序一開始就進(jìn)行初始化,就會(huì)導(dǎo)致程序啟動(dòng)時(shí)非常的緩慢
2?? 多個(gè)單例類之間如果有依賴關(guān)系餓漢模式就無法控制,比方說要求A類初始化時(shí)必須調(diào)用B,但是餓漢無法控制先后順序。

所以針對(duì)這些問題,就有了懶漢模式。

6.2 懶漢模式

第一次使用實(shí)例對(duì)象時(shí),創(chuàng)建對(duì)象(用的時(shí)候創(chuàng)建)。進(jìn)程啟動(dòng)無負(fù)載。多個(gè)單例實(shí)例啟動(dòng)順序自由控制。

我們可以直接對(duì)上面餓漢模式的代碼進(jìn)行修改,把靜態(tài)成員變量變成指針。然后把獲取的函數(shù)改變一下:

static Singleton& GetObj()
	{
		// 第一次調(diào)用才會(huì)創(chuàng)建對(duì)象
		if (_s == nullptr)
		{
			_s = new Singleton;
		}
		return *_s;
	}

整體代碼:

class Singleton
{
public:
	static Singleton& GetObj()
	{
		// 第一次調(diào)用才會(huì)創(chuàng)建對(duì)象
		if (_s == nullptr)
		{
			_s = new Singleton;
		}
		return *_s;
	}

	void insert(const std::string& s1, const std::string& s2)
	{
		_dict[s1] = s2;
	}

	void Print()
	{
		for (auto& e : _dict)
		{
			cout << e.first << "->" << e.second << endl;
		}
	}

	// 防拷貝
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
private:
	Singleton()
	{}

	std::map<std::string, std::string> _dict;
private:
	static Singleton* _s;// 聲明
};

Singleton* Singleton::_s = nullptr;// 定義

6.2.1 線程安全問題

上面的代碼存在問題,當(dāng)多個(gè)線程同時(shí)調(diào)用GetObj(),就會(huì)創(chuàng)建多個(gè)對(duì)象。所以為了線程安全我們要加鎖。為了保證鎖自動(dòng)銷毀,我們可以自定義一個(gè)鎖。

template <class Lock>
class LockAuto
{
public:
	LockAuto(Lock& lk)
		: _lk(lk)
	{
		_lk.lock();
	}

	~LockAuto()
	{
		_lk.unlock();
	}
private:
	Lock& _lk;
};

class Singleton
{
public:
	static Singleton& GetObj()
	{
		// 第一次調(diào)用才會(huì)創(chuàng)建對(duì)象
		if (_s == nullptr)// 只有第一次才用加鎖
		{
			LockAuto<mutex> lock(_mutex);
			if (_s == nullptr)
			{
				_s = new Singleton;
			}
		}
		return *_s;
	}

	void insert(const std::string& s1, const std::string& s2)
	{
		_dict[s1] = s2;
	}

	void Print()
	{
		for (auto& e : _dict)
		{
			cout << e.first << "->" << e.second << endl;
		}
	}

	// 防拷貝
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
private:
	Singleton()
	{}

	std::map<std::string, std::string> _dict;
private:
	static Singleton* _s;// 聲明
	static mutex _mutex;// 鎖
};

Singleton* Singleton::_s = nullptr;// 定義
mutex Singleton::_mutex;// 定義

6.2.2 新寫法

class Singleton
{
public:
	static Singleton& GetObj()
	{
		static Singleton dic;
		return dic;
	}

	void insert(const std::string& s1, const std::string& s2)
	{
		_dict[s1] = s2;
	}

	void Print()
	{
		for (auto& e : _dict)
		{
			cout << e.first << "->" << e.second << endl;
		}
	}

	// 防拷貝
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
private:
	Singleton()
	{}

	std::map<std::string, std::string> _dict;
};

這里就用了靜態(tài)局部變量只會(huì)在第一次定義的時(shí)候初始化。在C++11之前是不能保證線程安全的,但是C++11之后就可以了。文章來源地址http://www.zghlxwxcb.cn/news/detail-421828.html



到了這里,關(guān)于【C++】特殊類設(shè)計(jì)(單例模式)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 從C語言到C++_37(特殊類設(shè)計(jì)和C++類型轉(zhuǎn)換)單例模式

    從C語言到C++_37(特殊類設(shè)計(jì)和C++類型轉(zhuǎn)換)單例模式

    目錄 1. 特殊類設(shè)計(jì) 1.1 不能被拷貝的類 1.2 只能在堆上創(chuàng)建的類 1.3 只能在棧上創(chuàng)建的類 1.4 不能被繼承的類 1.5 只能創(chuàng)建一個(gè)對(duì)象的類(單例模式)(重點(diǎn)) 1.5.1 餓漢模式 1.5.2?懶漢模式 2.?類型轉(zhuǎn)換 2.1 static_cast 2.2 reinterpret_cast 2.3 const_cast 2.4 dynamic_cast 3. RTTI(了解)和類型轉(zhuǎn)換常見面

    2024年02月10日
    瀏覽(26)
  • 【重點(diǎn):單例模式】特殊類設(shè)計(jì)

    【重點(diǎn):單例模式】特殊類設(shè)計(jì)

    方式如下: 將構(gòu)造函數(shù)設(shè)置為私有,防止外部直接調(diào)用構(gòu)造函數(shù)在棧上創(chuàng)建對(duì)象。 向外部提供一個(gè)獲取對(duì)象的static接口,該接口在堆上創(chuàng)建一個(gè)對(duì)象并返回。 將拷貝構(gòu)造函數(shù)設(shè)置為私有,并且只聲明不實(shí)現(xiàn),防止外部調(diào)用拷貝構(gòu)造函數(shù)在棧上創(chuàng)建對(duì)象。 說明一下: 向外部

    2024年02月15日
    瀏覽(22)
  • 特殊類的設(shè)計(jì)(含單例模式)

    特殊類的設(shè)計(jì)(含單例模式)

    拷貝只會(huì)放生在兩個(gè)場景中:拷貝構(gòu)造函數(shù)以及賦值運(yùn)算符重載,因此 想要讓一個(gè)類禁止拷貝,只需讓該類不能調(diào)用拷貝構(gòu)造函數(shù)以及賦值運(yùn)算符重載即可。 C++98: 將拷貝構(gòu)造函數(shù)與賦值運(yùn)算符重載只聲明不定義,并且將其訪問權(quán)限設(shè)置為私有即可。 原因: 設(shè)置成私有:如

    2024年01月23日
    瀏覽(14)
  • 【C++】設(shè)計(jì)模式-單例模式

    【C++】設(shè)計(jì)模式-單例模式

    目錄 一、單例模式 單例模式的三個(gè)要點(diǎn) 針對(duì)上述三要點(diǎn)的解決方案 常用的兩類單例模式 ?二、懶漢模式實(shí)現(xiàn) 1.基本實(shí)現(xiàn) 2.鎖+靜態(tài)成員析構(gòu)單例 3.雙層檢查鎖定優(yōu)化 4.雙層檢查鎖定+智能指針 三、餓漢模式實(shí)現(xiàn) 1.基礎(chǔ)實(shí)現(xiàn) 2.嵌套內(nèi)部類解決內(nèi)存泄漏 3.智能指針解決內(nèi)存泄漏

    2024年02月16日
    瀏覽(15)
  • C++設(shè)計(jì)模式代碼--單例模式

    參考:5. 單例模式(Singleton) (yuque.com) 1、什么是單例模式 保證一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)訪問該實(shí)例的全局節(jié)點(diǎn); 2、什么情況下需要單例模式 某個(gè)類的對(duì)象在軟件運(yùn)行之初就創(chuàng)建,并且在軟件的很多地方都需要讀寫這個(gè)類的信息;使用單例模式的話,類對(duì)象就只要

    2024年02月03日
    瀏覽(31)
  • C++設(shè)計(jì)模式:單例模式(十)

    C++設(shè)計(jì)模式:單例模式(十)

    1、單例設(shè)計(jì)模式 單例設(shè)計(jì)模式,使用的頻率比較高,整個(gè)項(xiàng)目中某個(gè)特殊的類對(duì)象只能創(chuàng)建一個(gè) 并且該類只對(duì)外暴露一個(gè)public方法用來獲得這個(gè)對(duì)象。 單例設(shè)計(jì)模式又分懶漢式和餓漢式,同時(shí)對(duì)于懶漢式在多線程并發(fā)的情況下存在線程安全問題 餓漢式:類加載的準(zhǔn)備階段

    2024年04月14日
    瀏覽(33)
  • 【設(shè)計(jì)模式】C++單例模式詳解

    ?個(gè)類僅有?個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn),該實(shí)例被所有程序模塊共享。 那么,我們必須保證: 該類不能被復(fù)制;也不能被公開的創(chuàng)造。 對(duì)于 C++ 來說,它的構(gòu)造函數(shù),拷貝構(gòu)造函數(shù)和賦值函數(shù)都不能被公開調(diào)用。 單例模式又分為 懶漢模式 和 餓漢模式 ,它們

    2024年02月05日
    瀏覽(22)
  • c++設(shè)計(jì)模式之單例模式

    一個(gè)類無論創(chuàng)建多少對(duì)象 , 都只能得到一個(gè)實(shí)例 如上述代碼中,我們通過new運(yùn)算符創(chuàng)建出了類A的三個(gè)對(duì)象實(shí)例,而我們現(xiàn)在要做的是,如何設(shè)計(jì)類A,使得上述代碼運(yùn)行之后永遠(yuǎn)只產(chǎn)生同一個(gè)對(duì)象實(shí)例 ????????我們知道,一個(gè)類對(duì)象是通過這個(gè)類的構(gòu)造函數(shù)創(chuàng)建的,因此

    2024年01月19日
    瀏覽(26)
  • C++設(shè)計(jì)模式創(chuàng)建型之單例模式

    一、概述 ? ? ? ? 單例模式也稱單態(tài)模式,是一種創(chuàng)建型模式,用于創(chuàng)建只能產(chǎn)生一個(gè)對(duì)象實(shí)例的類。例如,項(xiàng)目中只存在一個(gè)聲音管理系統(tǒng)、一個(gè)配置系統(tǒng)、一個(gè)文件管理系統(tǒng)、一個(gè)日志系統(tǒng)等,甚至如果吧整個(gè)Windows操作系統(tǒng)看成一個(gè)項(xiàng)目,那么其中只存在一個(gè)任務(wù)管理

    2024年02月14日
    瀏覽(29)
  • C++面試:單例模式、工廠模式等簡單的設(shè)計(jì)模式 & 創(chuàng)建型、結(jié)構(gòu)型、行為型設(shè)計(jì)模式的應(yīng)用技巧

    ????????理解和能夠?qū)崿F(xiàn)基本的設(shè)計(jì)模式是非常重要的。這里,我們將探討兩種常見的設(shè)計(jì)模式:單例模式和工廠模式,并提供一些面試準(zhǔn)備的建議。 目錄 單例模式 (Singleton Pattern) 工廠模式 (Factory Pattern) 面試準(zhǔn)備? 1. 理解設(shè)計(jì)模式的基本概念 2. 掌握實(shí)現(xiàn)細(xì)節(jié) 3. 討論優(yōu)缺

    2024年02月01日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包