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

C++適用入門同學(xué)的模板講解

 更新時間:2022年07月14日 08:58:55   作者:Yuucho  
人們需要編寫多個形式和功能都相似的函數(shù),因此有了函數(shù)模板來減少重復(fù)勞動;人們也需要編寫多個形式和功能都相似的類,于是?C++?引人了類模板的概念,編譯器從類模板可以自動生成多個類,避免了程序員的重復(fù)勞動

1. 泛型編程

C++下一個針對C語言不足而設(shè)計的語法就叫作模板,模板的這種思想叫作泛型編程。

泛型編程的意思是:

我們以前C語言寫代碼是不是都是針對一種類型,比如我們寫個Swap,寫個排序,我們換一個類型,程序都得掛。

而泛型編程不再是針對某種類型,能夠適應(yīng)廣泛的類型。泛型編程用的一個東西就叫作模板。

博主先帶大家來舉一個簡單的范例:

如何實(shí)現(xiàn)一個通用的交換函數(shù)呢?

void Swap(int& left, int& right)
{
int temp = left;
left = right;
right = temp;
}
void Swap(double& left, double& right)
{
double temp = left;
left = right;
right = temp;
}
void Swap(char& left, char& right)
{
char temp = left;
left = right;
right = temp;
}
......

即使C++有函數(shù)重載,寫一個Swap是不是也要寫很多的代碼呀!但是這些代碼都是相似的,int要寫一個,double要寫一個,char要寫一個,日期類要寫一個,自定義類型都得寫一個,全部都得寫一個。有意思沒?

ok,C++就給出了一個模板,讓編譯器根據(jù)不同的實(shí)參類型自動推導(dǎo)生成相應(yīng)的一系列類似的代碼。

模板是將一個事物的結(jié)構(gòu)規(guī)律予以固定化、標(biāo)準(zhǔn)化的成果,它體現(xiàn)的是結(jié)構(gòu)形式的標(biāo)準(zhǔn)化。

模板分為函數(shù)模板和類模板:

2. 函數(shù)模板

2.1 函數(shù)模板概念

函數(shù)模板代表了一個函數(shù)家族,該函數(shù)模板與類型無關(guān),在使用時被參數(shù)化,根據(jù)實(shí)參類型產(chǎn)生函數(shù)的特定類型版本。

2.2 函數(shù)模板格式

注意:typename是用來定義模板參數(shù)關(guān)鍵字,也可以使用class(切記:不能使用struct代替class)

template<typename T1, typename T2,......,typename Tn>

返回值類型 函數(shù)名(參數(shù)列表){}

template<typename T>
void Swap( T& left, T& right)
{
	T temp = left;
	left = right;
	right = temp;
}

然后我們可以這樣調(diào)用:

int main()
{
	int a = 0, b = 1;
	double c = 2.2, d = 3.3;
	Swap(a, b);
	Swap(c, d);
	printf("a=%d b=%d\n", a, b);
	printf("c=%lf d=%lf\n", c, d);
	return 0;
}

愛思考的同學(xué)可能就會問這個函數(shù)模板到底是怎么做到的呢?

大家猜一猜這兩個Swap調(diào)用的是不是同一個函數(shù)?

ok,博主告訴大家,它們調(diào)用的肯定不是同一個函數(shù)。雖然它們看起是來調(diào)用了同一個函數(shù)(這是編譯器優(yōu)化的結(jié)果),但是它們調(diào)用的是模板自動生成的相應(yīng)函數(shù)。

2.3 函數(shù)模板的原理

函數(shù)模板是一個藍(lán)圖,它本身并不是函數(shù),是編譯器用使用方式產(chǎn)生特定具體類型函數(shù)的模具。

所以其實(shí)模板就是將本來應(yīng)該我們做的重復(fù)的事情交給了編譯器。

模板的實(shí)例化:

在編譯器編譯階段,對于模板函數(shù)的使用,編譯器需要根據(jù)傳入的實(shí)參類型來推演生成對應(yīng)類型的函數(shù)以供調(diào)用。比如:當(dāng)用double類型使用函數(shù)模板時,編譯器通過對實(shí)參類型的推演,將T確定為double類型,然后產(chǎn)生一份專門處理double類型的代碼,對于字符類型也是如此。

其實(shí)swap這個常用的小函數(shù),C++的庫里面有提供。大家想一想為什么C語言不提供,因?yàn)镃語言沒辦法提供,這是C語言語法的缺陷。

2.4 函數(shù)模板的實(shí)例化

用不同類型的參數(shù)使用函數(shù)模板時,稱為函數(shù)模板的實(shí)例化。模板參數(shù)實(shí)例化分為:隱式實(shí)例化和顯式實(shí)例化。

2.4.1顯式實(shí)例化

講到這,博主問大家一個問題:函數(shù)模板一定就是推演的嗎?不一定。

假設(shè),我們寫了一個沒有參數(shù)或者沒有用模板參數(shù)的func函數(shù),我們該怎么調(diào)用?

template<class T>  
T* func(int n)
{
	return new T[n];
}
int main()
{
	int* p1 = func(10);
	double* p2 = func(10);
	return 0;
}

我們這樣調(diào)用,編譯器能不能知道T的類型?是不是肯定不行呀:

這個時候函數(shù)模板就需要顯示實(shí)例化:在函數(shù)名后的<>中指定模板參數(shù)的實(shí)際類型。

模板參數(shù)很多用法和函數(shù)參數(shù)是很像的,也可以有缺省參數(shù)。只是說模板參數(shù)傳遞的是類型,函數(shù)參數(shù)傳遞的是對象值。

2.4.2 隱式實(shí)例化

讓編譯器根據(jù)實(shí)參推演模板參數(shù)的實(shí)際類型

template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
int main()
{
	int a1 = 10, a2 = 20;
	double d1 = 10.0, d2 = 20.0;
	Add(a1, a2);
	Add(d1, d2);
}

那如果我Add(a1, d2);這樣調(diào)用會怎么樣?大家看:

編譯器這個時候?yàn)殡y了,你到底想讓Tint呢?還是Tdouble呢?

那怎么辦,這個時候是不是就無法調(diào)用了。那我就想這樣調(diào)用怎么辦呢?

ok,也有。

此時有兩種處理方式:

1. 用戶自己來強(qiáng)制轉(zhuǎn)化

2. 使用顯式實(shí)例化

2.5 模板參數(shù)的匹配原則

這兩個函數(shù)能不能同時存在?

一個非模板函數(shù)可以和一個同名的函數(shù)模板同時存在,而且該函數(shù)模板還可以被實(shí)例化為這個非模板函數(shù)。

// 專門處理int的加法函數(shù)
int Add(int left, int right)
{
	return left + right;
}
// 通用加法函數(shù)
template<class T>
T Add(T left, T right)
{
	return left + right;
}

對于非模板函數(shù)和同名函數(shù)模板,如果其他條件都相同,在調(diào)動時會優(yōu)先調(diào)用非模板函數(shù)而不會從該模板產(chǎn)生出一個實(shí)例。如果模板可以產(chǎn)生一個具有更好匹配的函數(shù), 那么將選擇模板。

也可以指定調(diào)用模板:

模板函數(shù)不允許自動類型轉(zhuǎn)換,但普通函數(shù)可以進(jìn)行自動類型轉(zhuǎn)換

所以當(dāng)一個匹配既沒有非模板函數(shù),也沒有函數(shù)模板可以匹配到的時候,會嘗試通過自動類型轉(zhuǎn)換調(diào)用到非模板函數(shù)(前提是可以轉(zhuǎn)換為非模板函數(shù)的參數(shù)類型)

3. 類模板

我們以前C語言要解決類型更換的問題用的是typedef,但是typedef不能解決全部的問題。

假設(shè)我們用以前的方法寫一個棧:

typedef int STDataType;
class Stack
{
public:
	Stack(int capacity = 0)
	{
		_a = new STDataType[capacity];
		_capacity = capacity;
		_top = 0;
	}
	~Stack()
	{
		cout << "~Stack()" << endl;
		delete[] _a;
		_capacity = 0;
		_top = 0;
	}
	void Push(STDataType x)
	{}
private:
	STDataType* _a;
	int _top;
	int _capacity;
};
int main()
{
	Stack st1; // int
	Stack st2; // double
	return 0;
}

C語言typedef的真正缺陷在于:如果我在一個程序里面定義了一個棧,那么不可能同時存在兩個存儲類型不同的棧。

C++由此提供了一個類模板。

3.1 類模板的定義格式

template<class T1, class T2, ..., class Tn>
class 類模板名
{
// 類內(nèi)成員定義
};

此時我們寫一個棧的模板:

template<class T>
class Stack
{
public:
	Stack(int capacity = 0)
	{
		_a = new T[capacity];
		_capacity = capacity;
		_top = 0;
	}
	~Stack()
	{
		cout << "~Stack()" << endl;
		delete[] _a;
		_capacity = 0;
		_top = 0;
	}
	void Push(const T& x)
	{}
private:
	T* _a;
	int _top;
	int _capacity;
};

類模板和函數(shù)模板不一樣:函數(shù)模板可以自動推導(dǎo)。類模板不能推導(dǎo),因?yàn)槿绻x對象時構(gòu)造函數(shù)沒有傳參或者構(gòu)造函數(shù)沒有參數(shù),那就麻煩了,所以類模板得在調(diào)用的時候指定類型。

注意:Push的傳參不能傳值,因?yàn)榇鎯Φ念愋筒灰粯?,如果是自定義類型,還可能會考慮深拷貝的問題,代價就太大了,所以我們最好傳引用,引用實(shí)體不改變就加const。

3.2 類模板的實(shí)例化

類模板實(shí)例化與函數(shù)模板實(shí)例化不同,類模板實(shí)例化需要在類模板名字后跟<>,然后將實(shí)例化的類型放在<>中即可,類模板名字不是真正的類,而實(shí)例化的結(jié)果才是真正的類。

int main()
{
	//Stack是類名,Stack<int>才是類型
	Stack<int> st1; // int
	st1.Push(1);
	Stack<double> st2; // double
	st2.Push(2.2);
	return 0;
}

st1st2是兩個類,類型分別是Stack<int> 、 Stack<double>。

4 模板分離編譯

4.1 模板的分離編譯

//聲明
template<class T>  
void Swap(T& left, T& right);
template<class T>
class Vector//Vector不是具體的類,是編譯器根據(jù)被實(shí)例化的類型生成具體類的模具,其實(shí)就是順序表
{
public:
	Vector(size_t capacity = 10);
private:
	T* _pData;
	size_t _size;
	size_t _capacity;
};
//定義
template<class T >
void Swap(T& left, T& right)
{
	T temp = left;
	left = right;
	right = temp;
}
template<class T>
Vector<T>::Vector(size_t capacity)
	: _pData(new T[capacity])
	, _size(0)
	, _capacity(capacity)
{}

模板分離編譯和普通的函數(shù)分離編譯還是不同的,最大的不同是:雖然聲明的時候給了模板參數(shù),但是定義的時候還要聲明一次,不然編譯器不知道T是哪來的。

但是這里還有一個問題:模板不支持聲明和定義分別放在xxx.h和xxx.cpp中!會出現(xiàn)鏈接錯誤!

來,我們來玩一下:

為什么模板分離編譯會鏈接不上?

ok,其實(shí)這里和模板的實(shí)例化有關(guān)系。

大家想一想編譯器把template.i處理成template.s,能干什么事情?

編譯器是不是應(yīng)該把類和函數(shù)編譯了放在符號表里面去?但是大家想一想,編譯器能不能處理?

ok,編譯器根本無從下手,其實(shí)templa.i編譯之后是空的,template.o和符號表也是空的,全都是空的。因?yàn)榫幾g器沒辦法知道模板參數(shù)T是啥!

大家再看調(diào)用的地方能不能編譯過,調(diào)用的地方?jīng)]啥毛病,能過。但是調(diào)用Swap和實(shí)例化對象調(diào)用構(gòu)造函數(shù)時會去call相應(yīng)函數(shù)的地址(正常是鏈接時拿修飾過的函數(shù)名去符號表里找這個地址)。但是符號表是空的呀,所以模板分離編譯,鏈接時找不到這些函數(shù)模板調(diào)用的地址。

4.2 解決方法

第一種方法:(推薦使用)

將聲明和定義放到一個文件 “xxx.hpp” (.h+.cpp合在一起這樣命名更規(guī)范)里面或者xxx.h其實(shí)也是可以的。

這樣頭文件展開的時候,就是聲明和定義一起在test.cpp中展開了,這樣test.cpp在編譯的時候直接就把模板實(shí)例化了,調(diào)用的時候也是直接call函數(shù)的地址了,不用鏈接的時候去找了。

第二種方法:模板定義的位置顯式實(shí)例化。這種方法不實(shí)用,不推薦使用。

到此這篇關(guān)于C++適用入門同學(xué)的模板講解的文章就介紹到這了,更多相關(guān)C++模板內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • c語言實(shí)現(xiàn)輸入一組數(shù)自動從大到小排列的實(shí)例代碼

    c語言實(shí)現(xiàn)輸入一組數(shù)自動從大到小排列的實(shí)例代碼

    下面小編就為大家?guī)硪黄猚語言實(shí)現(xiàn)輸入一組數(shù)自動從大到小排列的實(shí)例代碼。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • c語言 數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)之字符串

    c語言 數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)之字符串

    這篇文章主要介紹了c語言 數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)之字符串的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • vscode使用cmake時將命令行參數(shù)傳遞給調(diào)試目標(biāo)的方法

    vscode使用cmake時將命令行參數(shù)傳遞給調(diào)試目標(biāo)的方法

    這篇文章主要介紹了vscode使用cmake時將命令行參數(shù)傳遞給調(diào)試目標(biāo),下面介紹了一個示例,將參數(shù)first_arg, second-arg和third arg傳遞給程序(此處需要注意,third arg中間雖然存在空格,但是仍然被視作一個參數(shù)),需要的朋友參考下吧
    2024-03-03
  • Qt使用QCustomPlot的實(shí)現(xiàn)示例

    Qt使用QCustomPlot的實(shí)現(xiàn)示例

    QCustomPlot是一個基于Qt C++的圖形庫,用于繪制和數(shù)據(jù)可視化,并為實(shí)時可視化應(yīng)用程序提供高性能服務(wù),本文主要介紹了Qt使用QCustomPlot的實(shí)現(xiàn)示例,感興趣的可以了解一下
    2024-01-01
  • 帶你了解如何用C++合并兩個有序鏈表

    帶你了解如何用C++合并兩個有序鏈表

    這篇文章主要介紹了c++ 如何合并兩個有序鏈表,小編感覺這篇文章還不錯,希望能幫助大家更好的理解和學(xué)習(xí)C++,感興趣的朋友可以了解下
    2021-08-08
  • C++ vector的基本使用示例詳解

    C++ vector的基本使用示例詳解

    這篇文章主要介紹了C++ vector的基本使用,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • Qt使用Json的項目實(shí)踐

    Qt使用Json的項目實(shí)踐

    JSON是一種對源自Javascript的對象數(shù)據(jù)進(jìn)行編碼的格式,但現(xiàn)在被廣泛用作互聯(lián)網(wǎng)上的數(shù)據(jù)交換格式,本文主要介紹了Qt使用Json的項目實(shí)踐,詳細(xì)的介紹了主要使用的類以及Json實(shí)戰(zhàn),感興趣的可以了解一下
    2023-09-09
  • Matlab控制電腦攝像實(shí)現(xiàn)實(shí)時人臉檢測和識別詳解

    Matlab控制電腦攝像實(shí)現(xiàn)實(shí)時人臉檢測和識別詳解

    人臉識別過程主要由四個階段組成:人臉檢測、圖像預(yù)處理、面部特征提取和特征識別。這篇文章主要介紹了如何使用MATLAB控制筆記本電腦的攝像頭,并進(jìn)行實(shí)時人臉檢測和識別,需要的可以參考一下
    2022-10-10
  • 關(guān)于C語言和命令行之間的交互問題

    關(guān)于C語言和命令行之間的交互問題

    這篇文章主要介紹了C語言和命令行之間的交互,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-07-07
  • 詳解C++函數(shù)類型與重載函數(shù)

    詳解C++函數(shù)類型與重載函數(shù)

    這篇文章主要為大家介紹了C++函數(shù)類型與重載函數(shù),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11

最新評論

海门市| 兰州市| 兴山县| 手游| 延川县| 台江县| 宁国市| 诏安县| 云梦县| 双桥区| 台北县| 丰顺县| 呼和浩特市| 威海市| 大渡口区| 荥阳市| 南汇区| 项城市| 景洪市| 崇信县| 凌云县| 阿坝| 临桂县| 克山县| 奉节县| 丰镇市| 姚安县| 湘潭市| 和平县| 汶川县| 阳江市| 连平县| 怀安县| 宜兰县| 调兵山市| 多伦县| 凌云县| 类乌齐县| 房山区| 富蕴县| 佛学|