C++中类模板的深入理解
1,多参数类模板:
1,类模板可以定义任意多个不同的类型参数;
1,代码示例:
1 template <typename T1, typename T2>
2 class Test
3 {
4 public:
5 void add(T1 a, T2 a);
6 };
7
8 Test<int, float> t;
2,类模板可以被特化:

1,指定类模板的特定实现;
2,部分类型参数必须显示指定;
3,根据类型参数分开实现类模板;
3,类模板的特化类型:

1,部分特化 - 用特定规则约束类型参数;
1,上面的为部分特化;
2,完全特化 - 完全显示指定类型参数;
4,类模板的特化编程实验:
1 #include <iostream>
2 #include <string>
3
4 using namespace std;
5
6 template
7 < typename T1, typename T2 >
8 class Test
9 {
10 public:
11 void add(T1 a, T2 b)
12 {
13 cout << "void add(T1 a, T2 b)" << endl;
14 cout << a + b << endl;
15 }
16 };
17
18 /* 关于上述第一个类模板的特殊实现,关于指针的特化实现 */
19 template
20 < typename T1, typename T2 >
21 class Test < T1*, T2* > // 关于指针的特化实现
22 {
23 public:
24 void add(T1* a, T2* b)
25 {
26 cout << "void add(T1* a, T2* b)" << endl;
27 cout << *a + *b << endl;
28 }
29 };
30
31 /* 定义上述第一个类模板的特殊实现,即当Test 类模板的两个类型参数完全相同时,使用这个实现;编译器并不认为在这里重新定义了一个新的模板,它认为这里是在定义第一个类模板的特殊实现;这里是部分特化;
32 */
33 template
34 < typename T >
35 class Test < T, T > // Test 类模板的两个类型参数完全相同时,使用这个实现;
36 {
37 public:
38 void add(T a, T b)
39 {
40 cout << "void add(T a, T b)" << endl;
41 cout << a + b << endl;
42 }
43
44 void print() // 特化实现可以重新定义新的函数;
45 {
46 cout << "class Test < T, T >" << endl;
47 }
48 };
49
50 /* 定义上述第一个类模板的特殊实现,当 T1 == void* 并且 T2 == void* 时,使用这个实现; */
51 template
52 < > // 没有泛指类型;
53 class Test < void*, void* > // 当 T1 == void* 并且 T2 == void* 时
54 {
55 public:
56 void add(void* a, void* b)
57 {
58 cout << "void add(void* a, void* b)" << endl;
59 cout << "Error to add void* param..." << endl;
60 }
61 };
62
63 int main()
64 {
65 Test<int, float> t1; // 使用第一个类模板;
66 Test<long, long> t2; // 使用第三个类模板,特化实现;
67 Test<void*, void*> t3; // 使用第四个类模板,特化实现;
68
69 t1.add(1, 2.5); // void add(T1 a, T2 b) 3.5;
70
71 t2.add(5, 5); // void add(T a, Tb) 10;
72 t2.print(); // class Test < T, T >
73
74 t3.add(NULL, NULL); // void add(void* a, void* b);Error to add void* param...;
75
76 Test<int*, double*> t4; // 未有定义指针特化时,编译器显示 14 行:error: invalid operands of types 'int*' and 'double*' to binary 'operator+';
77 // 特化指针后,打印 void add(T1* a, T2* b);
78 int a = 1;
79 double b = 0.1;
80
81 t4.add(&a, &b); // 1.1
82
83 return 0;
84 }
1,类模板的特化实现表象上面好像定义了不同的类模板,但其实我们仅仅是根据需要将一个类模板分开成不同的情况来实现;
2,编译器编译过后根据我们使用的类型参数来决定究竟是哪一种实现;
5,类模板特化注意事项:
1,特化只是模板的分开实现:
1,本质上是同一个类模板;
2,仅仅是将模板根据需要分开来实现;
2,特化类模板的使用方式是统一的;
1,必须显示指定每一个类型参数;
2,类模板特化与重定义有区别吗?函数模板可以特化吗?
1,有区别;
3,特化的深度分析:
1,重定义和特化的不同:
1,重定义:
1,一个类模板和一个新类(或者两个类模板);
1,重定义本质是要么是实现了两个类模板,要么是一个类模板加上 一个新的类;
2,特化本质是只实现同一个类模板,特化的目的仅仅是考虑一些特殊的情况类模板应该如何工作;
2,使用的时候需要考虑如何选择的问题;
1,使用的时候没有统一的方式,要选择用类模板的种类或用新的类;
2,特化:
1,以统一的方式使用类模板和特化类;
2,编译器自动优先选择特化类;
1,能用特化就不要重定义;
2,函数模板只支持类型参数完全特化:
1,代码示例:
1 template < typename T> // 函数模板定义
2 bool Equal(T a, T b)
3 {
4 return a == b;
5 }
6
7 template < > // 函数模板完全特化
8 bool Equal<void *>(void* a, void* b)
9 {
10 return a == b;
11 }
3,特化的深入理解编程实验:
1 #include <iostream>
2 #include <string>
3
4 using namespace std;
5
6 /* 以下是类模板的重定义实现 */
7 template
8 < typename T1, typename T2 >
9 class Test
10 {
11 public:
12 void add(T1 a, T2 b)
13 {
14 cout << "void add(T1 a, T2 b)" << endl;
15 cout << a + b << endl;
16 }
17 };
18
19 /*
20 template
21 < >
22 class Test < void*, void* > // 当 T1 == void* 并且 T2 == void* 时
23 {
24 public:
25 void add(void* a, void* b)
26 {
27 cout << "void add(void* a, void* b)" << endl;
28 cout << "Error to add void* param..." << endl;
29 }
30 };
31 */
32
33 /* 类模板的重定义,重新实现上面注释的模板特化,处理指针相加 */
34 class Test_Void
35 {
36 public:
37 void add(void* a, void* b)
38 {
39 cout << "void add(void* a, void* b)" << endl;
40 cout << "Error to add void* param..." << endl;
41 }
42 };
43
44
45 /* 以下是函数模板的特化实验 */
46
47 template
48 < typename T >
49 bool Equal(T a, T b)
50 {
51 cout << "bool Equal(T a, T b)" << endl;
52
53 return a == b;
54 }
55
56 /* 函数完全特化解决浮点数比较问题 */
57 template
58 < >
59 bool Equal<double>(double a, double b)
60 {
61 const double delta = 0.00000000000001;
62 double r = a - b;
63
64 cout << "bool Equal<double>(double a, double b)" << endl;
65
66 return (-delta < r) && (r < delta);
67 }
68
69 /* 直接重载 */
70 bool Equal(double a, double b)
71 {
72 const double delta = 0.00000000000001;
73 double r = a - b;
74
75 cout << "bool Equal(double a, double b)" << endl;
76
77 return (-delta < r) && (r < delta);
78 }
79
80 int main()
81 {
82 Test<void*, void*> t3; // 这里错误了,要用 Test_Void t3; 这样的 定义方式,因为重定义了类的实现方式,注销了模板特化方式;写代码时,要时刻考虑究竟是要使用类模板 还是要使用新类,这就是弊端,所以能特化时,就不要重新定义、重新实现;
83
84 cout << Equal( 1, 1 ) << endl; // bool Equal(T a, T b) 1
85 cout << Equal<>( 0.001, 0.001 ) << endl; // 用相等符号比较两个浮点数是否相等是有问题的;用了特化后:bool Equal<double>(double a, double b) 1
86 cout << Equal( 0.001, 0.001 ) << endl; // bool Equal(double a, double b) 1;这里调用全局重载函数,因为编译器会优先寻找全局重载函数;
87
88 return 0;
89 }
4,工程中的建议:
1,当需要重载函数模板时,优先考虑使用模板特化;当模板特化无法满足需求,再使用函数重载!
4,小结:
1,类模板可以定义任意多个不同的类型参数;
2,类模板可以被部分特化和完全特化;
3,特化的本质是模板的分开实现;
4,函数模板只支持完全特化;
5,工程中使用模板特化代替类(函数)重定义;


浙公网安备 33010602011771号