最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++特殊類設(shè)計概念與示例講解

 更新時間:2023年04月22日 11:27:51   作者:命由己造~  
本文介紹C++中三種特殊類設(shè)計模式:單例模式、工廠模式和代理模式。通過詳細講解每種設(shè)計模式的實現(xiàn)原理和應(yīng)用場景,幫助讀者理解和掌握這些常用的面向?qū)ο笤O(shè)計模式,并提供示例代碼和技巧,便于實際應(yīng)用

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

設(shè)計模式是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類的、代碼設(shè)計經(jīng)驗的總結(jié)。

使用設(shè)計模式的目的:為了代碼可重用性、讓代碼更容易被他人理解、保證代碼可靠性。

根本原因是為了代碼復(fù)用,增加可維護性。

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

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

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

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

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

設(shè)計原因:

1?? 私有:如果聲明成共有,那么就可以在類外面實現(xiàn)定義。

2?? 只聲明不定義:因為如果不聲明編譯器會默認生成這兩個的默認成員函數(shù)。而不定義是因為該函數(shù)不會被調(diào)用,就不用寫了,這樣編譯的時候就會出現(xiàn)鏈接錯誤。

而在C++11中引入了關(guān)鍵字——delete。

如果在默認成員函數(shù)后跟上=delete,表示讓編譯器刪除掉該默認成員函數(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è)計一個只能在堆上創(chuàng)建對象的類

3.1 私有構(gòu)造

首先要把構(gòu)造函數(shù)給私有,不然這個類就可以在任意位置被創(chuàng)建。而構(gòu)造函數(shù)被私有了以后我們怎么創(chuàng)建對象呢?

我們可以在定義一個成員函數(shù),讓這個函數(shù)在堆上申請空間,但我們知道必須現(xiàn)有對象才能調(diào)用成員函數(shù)。所以我們就把這個函數(shù)設(shè)置成靜態(tài)成員函數(shù)。

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

但是這樣也不完全對,如果我們這么寫:

class OnlyHeap
{
public:
	static OnlyHeap* GetObj()
	{
		return new OnlyHeap;
	}
private:
	OnlyHeap()
	{}
};
int main()
{
	OnlyHeap* hp1 = OnlyHeap::GetObj();
	OnlyHeap hp2(*hp1);
	return 0;
}

這里的hp2就是棧上的對象。所以我們也要把拷貝構(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)建成功,因為對象銷毀的時候會調(diào)用析構(gòu)函數(shù),但是這里的析構(gòu)是私有的,所以該對象無法調(diào)用。

但是我們要銷毀hp2該怎么辦呢?

我們可以定義一個成員函數(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è)計一個只能在棧上創(chuàng)建對象的類

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

class StackOnly
{
public:
	static StackOnly GetObj()
	{
		return StackOnly();
	}
private:
	StackOnly()
	{}
};
int main()
{
	StackOnly hp = StackOnly::GetObj();
	return 0;
}

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

static StackOnly hp2 = StackOnly::GetObj();

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

在C++98,為了不讓子類繼承,我們可以把構(gòu)造函數(shù)私有化,因為子類需要先調(diào)用父類的構(gòu)造函數(shù)初始化父類的那一部分成員。

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

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

class NoInherit final
{
public:
private:
};

六、單例模式

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

單例模式的特點就是全局只有一個唯一對象。

6.1 餓漢模式

怎么能做到全局只是用一個對象呢,比方說我們現(xiàn)在想要實現(xiàn)一個英漢字典,首先我們要把構(gòu)造函數(shù)私有,不然無法阻止創(chuàng)建對象。然后我們可以在類里面定義一個自己類型的靜態(tài)成員變量,作用域是全局的。因為對比定義在外邊的靜態(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;
}

餓漢模式有什么特點呢?

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

餓漢模式有什么缺點呢?

1?? 如果單例對象構(gòu)造十分耗時或者占用很多資源,比如加載插件啊, 初始化網(wǎng)絡(luò)連接啊,讀取文件啊等等,而有可能該對象程序運行時不會用到,那么也要在程序一開始就進行初始化,就會導(dǎo)致程序啟動時非常的緩慢。

2?? 多個單例類之間如果有依賴關(guān)系餓漢模式就無法控制,比方說要求A類初始化時必須調(diào)用B,但是餓漢無法控制先后順序。

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

6.2 懶漢模式

第一次使用實例對象時,創(chuàng)建對象(用的時候創(chuàng)建)。進程啟動無負載。多個單例實例啟動順序自由控制。

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

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

整體代碼:

class Singleton
{
public:
	static Singleton& GetObj()
	{
		// 第一次調(diào)用才會創(chuàng)建對象
		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 線程安全問題

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

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)用才會創(chuàng)建對象
		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)局部變量只會在第一次定義的時候初始化。在C++11之前是不能保證線程安全的,但是C++11之后就可以了。

到此這篇關(guān)于C++特殊類設(shè)計概念與示例講解的文章就介紹到這了,更多相關(guān)C++特殊類設(shè)計內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺談C++11的std::function源碼解析

    淺談C++11的std::function源碼解析

    類模版std::function是一種通用的多態(tài)函數(shù)包裝器std::function的實例可以對任何可以調(diào)用的目標實體進行存儲、復(fù)制、和調(diào)用操作,本文詳細的介紹一下,感興趣的可以了解一下
    2021-06-06
  • linux c多線程編程實例代碼

    linux c多線程編程實例代碼

    這篇文章主要介紹了linux系統(tǒng)中的c多線程編程實例,大家可以參考使用以下代碼
    2013-11-11
  • C語言實現(xiàn)隨機抽取紙牌程序

    C語言實現(xiàn)隨機抽取紙牌程序

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)隨機抽取紙牌程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C++ pair的基本用法總結(jié)整理

    C++ pair的基本用法總結(jié)整理

    這篇文章主要介紹了C++ pair的基本用法總結(jié)整理,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • C++中 Sort函數(shù)詳細解析

    C++中 Sort函數(shù)詳細解析

    這篇文章主要介紹了C++中 Sort函數(shù)詳細解析,sort函數(shù)是algorithm庫下的一個函數(shù),sort函數(shù)是不穩(wěn)定的,即大小相同的元素在排序后相對順序可能發(fā)生改變
    2022-08-08
  • DLL加載設(shè)置相對路徑的方法

    DLL加載設(shè)置相對路徑的方法

    這篇文章給大家介紹了DLL加載設(shè)置相對路徑的方法,非常不錯,具有一定的參考借鑒加載,需要的朋友參考下吧
    2018-08-08
  • C++中如何調(diào)用C語言的代碼實現(xiàn)

    C++中如何調(diào)用C語言的代碼實現(xiàn)

    這篇文章主要介紹了C++中如何調(diào)用C語言的代碼實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • C++使用GDAL庫實現(xiàn)Tiff文件的讀取

    C++使用GDAL庫實現(xiàn)Tiff文件的讀取

    這篇文章主要為大家詳細介紹了C++使用GDAL庫實現(xiàn)Tiff文件的讀取的相關(guān)知識,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-03-03
  • 一篇文章讓你徹底明白c++11增加的變參數(shù)模板

    一篇文章讓你徹底明白c++11增加的變參數(shù)模板

    C++11的新特性--可變模版參數(shù)(variadic templates)是C++11新增的最強大的特性之一,它對參數(shù)進行了高度泛化,它能表示0到任意個數(shù)、任意類型的參數(shù),這篇文章主要給大家詳細介紹了關(guān)于c++11增加的變參數(shù)模板的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • opencv3/C++ 離散余弦變換DCT方式

    opencv3/C++ 離散余弦變換DCT方式

    今天小編就為大家分享一篇opencv3/C++ 離散余弦變換DCT方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12

最新評論

富川| 乌兰县| 巩义市| 平利县| 喜德县| 长岛县| 察雅县| 朝阳区| 忻州市| 大洼县| 清远市| 广河县| 丰宁| 临安市| 铁岭县| 边坝县| 百色市| 武义县| 广德县| 鹿泉市| 丽江市| 澎湖县| 积石山| 彭阳县| 文成县| 邛崃市| 丹棱县| 晋州市| 十堰市| 延川县| 贵州省| 浠水县| 宁波市| 蒙山县| 韶山市| 仁寿县| 桃园县| 邵武市| 丹江口市| 阿克| 苏尼特左旗|