C++初始模板

模板

我們知道,如果要用一個交換函數,那麼要交換int型的兩個數,就需要寫一個int類型的交換函數,如果交換char類型的兩個字符,就需要寫一個char類型的交換函數。這樣會造成代碼的複用率低,雖然函數重載可以實現,但是函數的複用率仍然很低,且如果一個出錯,那可能所有重載都會出錯,爲了解決這一問題,C++中引入了模板這一概念。
首先需要了解一下泛型編程的概念:
編寫與類型無關的通用代碼,是代碼複用的一種手段。模板是泛型編程的基礎。

函數模板

函數模板:
函數模板代表了一個函數家族,該函數模板與類型無關,在使用時被參數化,根據實參類型產生函數的特定 類型版本。
函數模板格式:
template<typename/class T1, typename/class T2,…,typename/class Tn>
比如交換函數我們可以寫成
隱式實例化:編譯器自己會去匹配類型

template<class type>
void swap(type& left,type& right)
{
	type tmp = left;
	left = right;
	right = tmp;
}

這樣,每次調用swap函數時,編譯器會根據參數類型,自動確定類型,並進行交換。
注意:
函數模板是一個藍圖,它本身並不是函數,是編譯器用使用方式產生特定具體類型函數的模具。所以其實模 板就是將本來應該我們做的重複的事情交給了編譯器
在編譯器編譯階段,對於模板函數的使用,編譯器需要根據傳入的實參類型來推演生成對應類型的函數以供 調用。比如:當用double類型使用函數模板時,編譯器通過對實參類型的推演,將T確定爲double類型,然 後產生一份專門處理double類型的代碼,對於字符類型也是如此。

但是下面這樣使用是不對的:

template<class type>
void swap(type& left,type& right)
{
	type tmp = left;
	left = right;
	right = tmp;
}
int main()
{
	int a = 10;
	char b = 'a';
	swap(a,b);
}

因爲編譯器無法斷定到底是int類型還是char類型
因此模板函數需要寫成這樣

template<class type,class> type2>
void swap(type& left,type2& right)
{
	type tmp = left;
	left = right;
	right = tmp;
}

顯示實例化:在函數名後的<>中指定模板參數的實際類型

template<class T>
T add(T& a,T& b)
{
  return a + b;
}
void test()
{
	int a = 10;
	double b = 20.5;
	add<int>(a,b);//顯式實例化成int類型
}

模板函數匹配原則

1.普通函數與模板函數共存時,如果普通函數的參數類型可以完全匹配,則執行普通函數,不進行模板函數的實例化。
2.普通函數與模板函數共存時,普通函數的參數類型不能完全匹配,但是實例化的函數可以完全匹配參數類型,則進行實例化。
3.普通函數與模板函數共存時,但是指定了需要實例化,則進行實例化。

類模板

格式如下:

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

例如:

template<class T1,class T2,class T3>
class date
{
public:
	date(T1 year,T2 month,T3 day)
		:_year(year)
		,_month(month)
		,_day(day)
		{}
private:
	T1 _year;
	T2 _month;
	T3 _day;
};

如果在類外定義類模板的成員函數,則需要加上泛性申明以及作用域(類名+<泛性參數>)。

template<class T1,class T2,classT3>
void date<T1,T2,T3>::display()
{
	cout<<_year<<" "<<_month<<' '<<_day<<endl;
}

注意:類模板實例化與函數模板實例化不同,類模板實例化需要在類模板名字後跟<>,然後將實例化的類型放在<> 中即可,類模板名字不是真正的類,而實例化的結果纔是真正的類。

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