C++模板

如果說C++和C區別,我認爲有兩個最大的改進;其一是實現了類的封裝,還有一個就是實現了多種相同動作的重載,今天我們提到的就是模板,小編認爲其也是屬於重載的一部分,模板相當於重新定義了個模具讓不同的對象產生類似的行爲,和重載區別不同的就是,模板是一個模板可以讓多個對象進行類似的動作,重載則是可以讓不同的對象進行不同的動作。
首先來看下模板的分類:
在這裏插入圖片描述
我們首先來看一下函數模板:
函數模板無疑就是由函數構成的模板
學習的時候,你可能會想,爲什麼要用模板?我C語言可以宏定義,可以設計函數,C++還可以重載函數?這些不香嗎?我非要再整個語法。我們來看個例子就發現。
for example:
交換兩個數

void swap(int *a, int *b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}

我們很輕鬆就寫出了這個例子,但是我們很快就發現這個完美,瑕疵很多,於是乎我們就想到了C++的重載:

void swap(float *a, float *b)
{
	float temp = *a;
	*a = *b;
	*b = temp;
}

我們繼續想,如果讓一個整形數和一個浮點數進行比較的話怎麼整?在實際應用中這個也經常出現啊?繼續重載。。。我們發現,真的是很煩,寫了好多函數,實際上就是將形參的類型改變了,實際上很多代碼還是沒有改變的,有沒有一個方法能夠讓這個代碼一下子簡介起來了?
這就需要用到我們的第一個,函數模板。
語法:
template
T是函數模板中的通用類型,在使用的時候被實例化。這個template是關鍵字。typename是類型名稱
有啥好處呢?

  1. 函數模板定義了一套適用於各種數據類型的一般操作;
  2. 函數模板可以不依賴與=於任何數據類型來定義算法的屬性。
    其調用方式有2種。
    隱式調用:
    允許將抽象的函數模板顯式的聲明爲某個具體的模板函數這個中間步驟,而直接用值調用函數模板,編譯將根據值的類型自動地實例化模板函數。
    直接上代碼:
template <class T>
void Swap(T& a,T&b)
{
	T temp = a;
	a = b;
	b = temp;
}

我們來看實際應用時這個操作的強度


int main()
{
	int i = 5;
	int j = 6;
	Swap(i, j);
	cout << i << j;
	char a = 'C';
	char b = 'J';
	Swap(a, b);
	cout << a << b;

	system("pause");
	return 0;
}

很方便,直接調,這就是所謂的隱式調用。
再來看顯式調用,隱式調用就是沒說這個類型是啥模板自動識別出來了類型,顯示調用正好相反,顯式調用需要先聲明類型是啥,直接根據數據類型調用相應的模板 。實際上就是將模板實例化,我們來看一組對比的代碼就清晰了。

在這裏插入圖片描述
通過這張圖我們可以清楚看到,我們可以輕易的實現相同類型的操作,因爲我們傳遞參數的時候都是T累型,但是如果參數類型 不一致了,編譯器就想,到底是將 T1類型強制抓換成T2還是將T2類型強制轉換成T1呢?這就需要我們用戶來處理。
解決辦法有兩個

  1. 將類型不一致的手動強制轉換成類型一致的;
  2. 顯示調用。
template<class T>
T Add(const T& left, const T&right)
{
	return left + right;
}
int main()
{
	int a = 5;
	int b = 6;
	cout<<Add(a, b) << endl;
	double c = 2.8525;
	double d = 6.2;
	cout << Add(c, d) << endl;
	cout << Add(a, (int)c) << endl;//方案一,強轉
	cout<<Add<double>(a, c)<<endl;//顯式調用
	system("pause");
	return 0;
}

接下來我們來看看模板匹配原則

  1. 模板函數時可以和非模板函數重名的,非模板函數還可以是模板函數的實例化成員;
  2. 當重名的模板函數和非模板函數在一起時默認調用的是非模板函數而不會從模板函數中實例化一個出來調用;
  3. 模板函數不允許自動類型強制轉換。

我們接下來看看類模板

有了函數模板的基礎,類模板就有了很好的鋪墊,類比模板函數,類模板就是說明這個類是模板,一個類應該具有哪些東西呢?來瞅代碼。

template<class T>
class Vector
{
private:
	T*  p_data;
	size_t size;
	size_t capacity;
public:
	Vector(size_t capacity = 10) : _pData(new T[capacity]), size(0), capacity(_capacity)
	{}
	~Vector();
	void pushbank(T &data);
	void popbank(T &data);
};
//注意:類模板中函數放在類外進行定義時,需要加模板參數列表
template <class T> 
Vector<T>::~Vector()
{ if (_pData)
delete[] _pData;
_size = _capacity = 0; 
}
int main()
{
	Vector<int>s1;
	Vector<double>s2;
	system("pause");
	return 0;
}

需要注意,模板類的名字不是真正的類,實例化的成員名字纔是模板類。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章