多引數類别範本
- 類别範本可以定義任意多個不同的型別引數
template < typename T1, typename T2 >
class Test
{
public:
void add(T1 a, T2 b);
};
==>
Test<int float> t;
類别範本可以被特化
- 指定類别範本的特定實現
- 部分型別引數必須顯示指定
- 根據型別引數分開實現類别範本
類别範本的特化型別
- 部分特化 – 用特定規則約束型別引數
- 完全特化 – 完全顯示指定型別引數
template
< typename T1, typename T2 >
class Test
{
};
部分特化 ==>
template
< typename T >
class Test <T, T>
{
};
完全特化 ==>
template
< >
class Test <int , int >
{
}
程式設計實驗: 類别範本的特化
#include <iostream>
using namespace std;
template
< typename T1, typename T2 >
class Test
{
public:
void add(T1 a, T2 b)
{
cout << "void add(T1 a, T2 b)" << endl;
cout << a + b << endl;
}
};
template
< typename T >
class Test < T, T > // 兩個型別引數相同時
{
public:
void add(T a, T b)
{
cout << "void add(T a, T b)" << endl;
cout << a + b << endl;
}
void print()
{
cout << "class Test < T, T >" << endl;
}
};
template
< typename T1, typename T2 > // 第一個型別引數為指標,第二個型別引數為指標時
class Test < T1*, T2*>
{
public:
void add(T1* a, T2* b)
{
cout << "void add(T1* a, T2* b)" << endl;
cout << *a + *b << endl;
}
};
template
< >
class Test < void*, void* > // T1 == void* , T2 == void* 時
{
public:
void add(void* a, void* b)
{
cout << "void add(void* a, void* b)" << endl;
cout << "Error to add* param..." << endl;
}
};
int main()
{
Test<int, float> t1;
Test<long, long> t2;
Test<void*, void*> t3;
t1.add(1, 2.5);
t2.add(5, 5);
t2.print();
t3.add(NULL, NULL);
Test<int*, double*> t4;
int a = 1;
double b = 0.1;
t4.add(&a, &b);
return 0;
}
輸出:
void add(T1 a, T2 b)
3.5
void add(T a, T b)
10
class Test < T, T >
void add(void* a, void* b)
Error to add* param...
void add(T1* a, T2* b)
1.1
類别範本特化注意事項
特化只是模板的分開實現
- 本質上是同一模板
特化類别範本的使用方式是統一的
- 必須顯示指定每一個型別引數
問題:
類别範本特化與重定義有區別嗎?
函式模板可以特化嗎?
特化的深度分析
重定義和特化不同
重定義
- 一個類别範本和一個新類(或者兩個類别範本)
- 使用的時候需要考慮如何選擇的問題
特化
- 以統一的方式使用類别範本和特化類
- 編譯器優先選擇特化類
- 函式模板只支援型別引數的完全特化
template
< typename T > // 函式模板定義
bool Equal(T a, T b)
{
return a == b;
}
template
< > // 函式模板完全特化
bool Equal<void*>(void* a, void* b)
{
return a == b;
}
程式設計實驗: 特化的深入理解
#include <iostream>
using namespace std;
template
< typename T1, typename T2 >
class Test
{
public:
void add(T1 a, T2 b)
{
cout << "void add(T1 a, T2 b)" << endl;
cout << a + b << endl;
}
};
/*
template
< >
class Test < void*, void* > // T1 == void* , T2 == void* 時
{
public:
void add(void* a, void* b)
{
cout << "void add(void* a, void* b)" << endl;
cout << "Error to add* param..." << endl;
}
};
*/
class Test_Void
{
public:
void add(void* a, void* b)
{
cout << "void add(void* a, void* b)" << endl;
cout << "Error to add* param..." << endl;
}
};
template
<typename T>
bool Equal(T a, T b)
{
cout << "bool Equal(T a, T b)" << endl;
return a == b;
}
template
< >
bool Equal<double>(double a, double b)
{
const double delta = 0.00000000001;
double r = a - b;
cout << "bool Equal<double>(double a, double b)" << endl;
return (-delta < r) && (r < delta);
}
bool Equal(double a, double b)
{
const double delta = 0.00000000001;
double r = a - b;
cout << "bool Equal(double a, double b)" << endl;
return (-delta < r) && (r < delta);
}
int main()
{
cout << Equal(1, 1) << endl;
cout << Equal(0.1, 0.1) << endl;
cout << Equal<>(0.1, 0.1) << endl;
return 0;
}
輸出:
bool Equal(T a, T b)
1
bool Equal(double a, double b)
1
bool Equal<double>(double a, double b)
1
工程中的建議
當需要過載函式模板時,優先考慮使用模板特化;
當模板特化無法滿足需求,再使用函式過載!
小結
- 類别範本可以定義任意多個不同的型別引數
- 類别範本可以被部分特化和完全特化
- 特化的本質是模板的分開實現
- 函式模板只支援完全特化
- 工程中使用模板特化代替類(函式)重定義
以上內容參考狄泰軟體學院系列課程,請大家保護原創!