函數模板
代碼示例
#include<iostream>
#include<string>
using namespace std;
//這裏使用函數模板 T
template<typename T>
void swapValue(T & a, T & b) {
T temp = a;
a = b;
b = temp;
}
//多個模板參數聲明方式
void func(T1 & t1,T2& t2) {
cout << t1 << endl;
cout << t2 << endl;
}
int main() {
int a = 10, b = 20;
cout << "a=" << a << " b=" << b << endl;
swapValue(a, b); //類型自動推導
cout << "a=" << a << " b=" << b << endl;
float c = 12.34, d = 23.43;
cout << "c=" << c << "\td=" << d << endl;
swapValue<float>(c, d);//顯式指定類型
cout << "c=" << c << "\td=" << d << endl;
func(a,c);
func<int,float>(b,d)
system("pause");
return 0;
}
函數模板的調用方式
-
自動推導類型
swapValue(a, b); //自動推導不會發生隱式類型轉換(例如 char-> int) int a =10; char c='v'; swapValue(a,c) //錯誤
-
顯式指定類型
swapValue<float>(c, d); //顯式類型會發生隱式類型轉換 int a =10; char c='v'; swapValue<int>(a,c) //正確
注意事項
-
自動推導出來的類型必須一致
template<typename T> void swapValue(T & a, T & b) { T temp = a; a = b; b = temp; } int a=10; float b=4.0; swapValue(a,b);//錯誤,類型不一致
-
必須推斷出參數的類型才能使用
template<typename T> void fun() { } int main(){ fun(); //錯誤,雖然函數沒有使用T,但是調用的時候編譯器需要推斷出T的類型 fun<int>();//正確,顯式指定一個類型即可 return 0; }
普通函數與函數模板的調用規則
-
如果函數模板和普通模板都可以調用,優先使用普通函數
-
可以通過空模板參數列表強制調用模板函數
fun<>();
-
函數模板可以發生重載
-
如果函數模板可以發生更好的匹配,則優先使用函數模板
模板具體化
#include<iostream>
#include<string>
using namespace std;
class Person {
public:
int age;
string name;
};
template<typename T>
void swapValue(T & a, T & b) {
T temp = a;
a = b;
b = temp;
}
//當傳入Person類型時,使用下面的具體化函數模板
template<> void swapValue(Person & p1, Person& p2) {
//int agetmp = p1.age;
//string nametmp = p1.name;
//p1.age = p2.age;
//p1.name = p2.name;
//p2.age = agetmp;
//p2.name = nametmp;
cout << "person swap is called..." << endl;
}
int main() {
int a = 10, b = 20;
cout << "a=" << a << " b=" << b << endl;
swapValue(a, b);
swapValue<int>(a, b);
cout << "a=" << a << " b=" << b << endl;
Person p1, p2;
swapValue(p1, p2);
system("pause");
return 0;
}
類模板
代碼示例
class Data
#include<iostream>
#include<string>
template<class T>
class Data
{
T data;
public:
void setValue(T v) {
data = v;
}
T getData() {
return data;
}
};
MainApp.cpp
int main(){
Data<int> data;
data.setValue(10);
cout << data.getData() << endl;
system("pause");
return 0;
}
類模板與函數模板的區別
- 類模板沒有自動類型推導
- 類模板在模板參數列表有默認類型參數
template<class T=int>
class Data
{
T data;
public:
void setValue(T v) {
data = v;
}
T getData() {
return data;
}
};
Data<> data; //這裏使用了默認類型參數,int,裏面可以不寫int,但是必須有尖括號<>
類模板作爲函數參數
- 三種方式
- 指定傳入類型
- 函數參數模板化
- 整個類模板化
template<class T=int>
class Data
{
T data;
public:
void setValue(T v) {
data = v;
}
T getData() {
return data;
}
};
//1.指定參數類型
void func1(Data<int>& d){
}
//2.參數類型模板化
template<typename T>
void func2(Data<T>& d){
// typeid()可以查看運行時參數的類型
cout<<typeid(T).name()<<endl;
}
//3.整個類模板化
template<typename T>
void func3(T& d){
}
類模板分文件編寫
- 普通類份文件編寫
Class.h
類的聲明Class.cpp
成員函數實現- 在main中包含
Class.h
- 對類模板而言,這樣會產生錯誤
- 將所有函數實現和聲明寫在一個文件中,並且命名爲
class.hpp
- 將所有函數實現和聲明寫在一個文件中,並且命名爲