1. 程式人生 > >函式模板、函式模板例項化、函式模板過載

函式模板、函式模板例項化、函式模板過載

模板是泛型程式設計的基礎。所謂泛型程式設計就是編寫與型別無關的邏輯程式碼,是一種複用的方式。模板分為模板函式和模板類。
如果是交換兩個資料,我們會定義對應型別的函式,比如要交換int型別資料,我們會定義int型別swap函式,如果是交換double型別資料,會再定義double型別交換函式。

void Swap(int& a, int &b)
{
	int c = a;
	a = b;
	b = c;
}
void Swap(double& a, double &b)
{
	double c = a;
	a = b;
	b = c;
}

這樣重複定義函式,程式碼重複度十分高,但是模板來說不需要使用者自己定義多種型別的函式,只需要定義一個模板就可以。模板分為函式模板和類模板。
函式模板


函式模板代表了一個函式家族,該函式模板與型別無關,在使用時被引數化,根據實參型別產生函式的特定型別版本
函式模板格式
template<typename 形參名1,typename 形參名2,typename形參名3>
返回型別 函式名(引數列表)
{…}
模板引數的定義既可以用typename,也可以用class(但是不能用struct),含義是相同的

template<typename T>  //模板引數的定義
void Swap( T& a,  T& b)
{
	T c = a;
	a = b;
	b = c;  //沒有例項化不會報錯
}
如果函式模板內部出現錯誤,編譯期間將不會報錯,因為是在例項化時才檢查模板內容,即當用Swap(a,b)會檢查模板內容
但是當函式模板頭出現問題時,會立即報錯

在這裡插入圖片描述

int main()
{
	int a = 1, b = 2;
	double c = 2.2, d = 3.4;
	Swap(a, b);
	Swap(c, d);
	cout << a << endl << b << endl;
	cout << c << endl << d << endl;

	system("pause");
	return 0;
}

彙編看函式模板例項化過程:
在這裡插入圖片描述
模板引數的原理:
模板本身不是類或函式,編譯器用模板產生指定的類或函式的特定型別版本,產生模板特定型別的過程稱為函式的模板例項化。
在這裡插入圖片描述


在使用函式模板時,編譯器需要根據傳入的實參型別,推演生成對應型別的函式來使用。
比如int型別使用函式模板時,編譯器通過對實參型別的推演,將確定為int型別,最後會生成int型別的資料交換函式
函式模板的例項化
用不同型別的引數使用函式模板時稱為函式模板的例項化,模板引數例項化分為隱式例項化和顯示例項化

template<typename T>
T Add(T a, T b)
{
	return a + b;
}
int main()
{
	int a = 1, b = 2;
	double c = 2.2, d = 3.4;
	//cout << Add(a, d) << endl;
	//在編譯期間,當編譯器看到該例項化時,需要推演實參型別,通過第一個引數a將T推演為int,
	//第二個推演為double,但是,模板引數型別只有一個T,編譯器無法確定將T推演為int或者double而出錯
	//因此需要將型別轉換為相同的,可以使用者自己強轉即隱式型別轉換,也可以用顯示型別轉換
	//隱式型別轉換
	cout << Add(a, b) << endl; //2
	cout << Add(a, (int)d) << endl;//4
	cout << Add((double)a, d) << endl; //4.4
	//顯示型別轉換:在函式名後加<具體型別>
	cout << Add<int>(a, d) << endl; //4
	system("pause");
	return 0;
}

在這裡插入圖片描述
函式模板過載

template<typename T>
T Add(T a, T b)
{
	return a + b;
}
int Add(int a, int b)
{
	return a + b;
}
template<typename T1,typename T2>
T2 Add(T1 a, T2 b)
{
	return a + b;
}
int main()
{
	int a = 1, b = 2;
	cout << Add(a, b) << endl;  //int Add(int a, int b),如果有現成函式就不用模板
	double c = 1.2, d = 3.5;
	//根據引數找不同模板例項化
	cout << Add(c, d) << endl; //T Add(T a, T b) 
	cout << Add(a, d) << endl; //T2 Add(T1 a, T2 b)
	system("pause");
	return 0;
}