类模板:数据的组织方式和数据元素的类型无关。(也就是存储和组织元素)。
(链表类,队列类)。不关心操作的数据元素类型,只关心操作方法。
语法:
template < typename T > // T 泛指类型,具体的元素类型 class Operator // 类模板名 { public: T function(T a, T b) // function 具体的操作方法 { } };
类模板定义具体对象:(必须显示的指定元素类型,编译器无法自动推导类型)
Operator<string> str_op; // 用类模板Operator定义一个操作元素为string类的对象str_op。编译器此处生成str_op类的实体。
编译器对类模板的处理:编译器通过具体参数和类模板在定义对象时生成类的实体。
编译器会对类模板本身代码进行一次编译,还会对参数替换后的类的代码进行一次编译。
注意:类模板在头文件里定义。
类模板的成员函数在外部实现时要加上模板<>声明。
类模板不能分开实现在不同的文件中。
template < typename T > // 类模板函数在外部实现时的声明方式 T Operator<T>::function(T a, T b) { /* do something */ }
加减乘除类模板的实现:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#ifndef _OPERATOR_H_ #define _OPERATOR_H_ template < typename T > class Operator { public: T add(T a, T b); T minus(T a, T b); T multiply(T a, T b); T divide(T a, T b); }; template < typename T > T Operator<T>::add(T a, T b) { return a + b; } template < typename T > T Operator<T>::minus(T a, T b) { return a - b; } template < typename T > T Operator<T>::multiply(T a, T b) { return a * b; } template < typename T > T Operator<T>::divide(T a, T b) { return a / b; } #endif
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <string> #include "Operator.h" using namespace std; int main() { Operator<int> op1; cout << op1.add(1, 2) << endl; cout << op1.multiply(4, 5) << endl; cout << op1.minus(5, 6) << endl; cout << op1.divide(10, 5) << endl; return 0; }
多参类模板:定义任意多个不同类型的参数模板
template < typename T1, typename T2 > // class Test // 多参类模板名 { public: void function(T1 a, T2 b) // 多参类模板的功能 { } }; Test<int,int> t; // 用类模板Test定义一个参数类型为int和int的类t。必须指定参数的类型。
类模板的特化:类模板的特殊形式。将一个类模板分开为不同的情况来实现。本质还同一个模板,
部分特化:特定规则约束类型参数
template < typename T> // class Test <T,T> // 使用Test类模板定义类时参数类型相同,则用部分特化模板 { public: void function(T a, T b) // { } };
完全特化:完全显示指定类型参数
template < > // 没有泛指参数 class Test <int,int> // 使用Test类模板定义类时指定了类参数为int,int。则使用完全特化模板 { public: void function(int a, int b) // { } };
编译器根据参数来判断使用哪种模板
#include <iostream> #include <string> using namespace std; template < typename T1, typename T2 > // 将模板分开为不同的情况来实现。 class Test { public: void function(T1 a, T2 b) { /* do something */ } }; template < typename T1, typename T2 > class Test < T1*, T2* > // 关于指针的特化实现 { public: void function(T1* a, T2* b) { /* do something */ } }; template < typename T > class Test < T, T > // 当 Test 类模板的两个类型参数完全相同时,使用这个实现 { public: void function(T a, T b) { /* do something */ } void function_1() { /* do something */ } }; template < > class Test < void*, void* > // 当 T1 == void* 并且 T2 == void* 时 { public: void function(void* a, void* b) { /* do something */ } }; int main() { Test<int, float> t1; // 使用模板 Test Test<long, long> t2; // 使用模板 Test < T, T > Test<void*, void*> t3; // 使用模板 Test < void*, void* > Test<int*, double*> t4; // 使用模板 Test < T1*, T2* > return 0; }
特化:统一的方式使用类模板和特化类
重定义:一个类模板和一个新的类