
模板Template指C程序设计设计语言中采用类型作为参数的程序设计支持通用程序设计。C 的标准库提供许多有用的函数大多结合了模板的观念如STL以及IO Stream。函数模板在c入门中很多人会接触swap(int, int)这样的函数类似代码如下:12345voidswap(inta ,int b) {inttemp a;a b;b temp;}但是如果是要支持long,string,自定义class的swap函数,代码和上述代码差不多只是类型不同这个时候就是我们定义swap的函数模板,就可以复用不同类型的swap函数代码函数模板的声明形式如下:12templateclassidentifier function_declaration;templatetypenameidentifier function_declaration;swap函数模板的声明和定义代码如下:1234//method.htemplatetypenameTvoidswap(T t1, T t2);#include method.cpp12345678//method.cpptemplatetypenameTvoidswap(T t1, T t2) {T tmpT;tmpT t1;t1 t2;t2 tmpT;}上述是模板的声明和定义了那模板如何实例化呢模板的实例化是编译器做的事情与程序员无关那么上述模板如何使用呢代码如下:12345678910//main.cpp#include stdio.h#include method.hintmain() {//模板方法intnum1 1, num2 2;swapint(num1, num2);printf(num1:%d, num2:%d\n, num1, num2);return0;}这里使用swap函数必须包含swap的定义否则编译会出错这个和一般的函数使用不一样。所以必须在method.h文件的最后一行加入#include method.cpp。类模板考虑我们写一个简单的栈的类这个栈可以支持int类型long类型string类型等等不利用类模板我们就要写三个以上的stack类其中代码基本一样通过类模板我们可以定义一个简单的栈模板再根据需要实例化为int栈long栈string栈。123456789101112131415//statck.htemplateclassTclassStack {public:Stack();~Stack();voidpush(T t);T pop();boolisEmpty();private:T *m_pT;intm_maxSize;intm_size;};#include stack.cpp1234567891011121314151617181920212223//stack.cpptemplateclassT StackT::Stack(){m_maxSize 100;m_size 0;m_pT newT[m_maxSize];}templateclassT StackT::~Stack() {delete[] m_pT ;}templateclassTvoidStackT::push(T t) {m_size;m_pT[m_size - 1] t;}templateclassT T StackT::pop() {T t m_pT[m_size - 1];m_size--;returnt;}templateclassTboolStackT::isEmpty() {returnm_size 0;}上述定义了一个类模板--栈这个栈很简单只是为了说明类模板如何使用而已最多只能支持100个元素入栈使用示例如下:1234567891011121314//main.cpp#include stdio.h#include stack.hintmain() {Stackint intStack;intStack.push(1);intStack.push(2);intStack.push(3);while(!intStack.isEmpty()) {printf(num:%d\n, intStack.pop());}return0;}模板参数模板可以有类型参数也可以有常规的类型参数int也可以有默认模板参数例如1templateclassT, T def_valclassStack{...}上述类模板的栈有一个限制就是最多只能支持100个元素我们可以使用模板参数配置这个栈的最大元素数,如果不配置就设置默认最大值为100代码如下:123456789101112131415//statck.htemplateclassT,intmaxsize 100classStack {public:Stack();~Stack();voidpush(T t);T pop();boolisEmpty();private:T *m_pT;intm_maxSize;intm_size;};#include stack.cpp1234567891011121314151617181920212223//stack.cpptemplateclassT,intmaxsize StackT, maxsize::Stack(){m_maxSize maxsize;m_size 0;m_pT newT[m_maxSize];}templateclassT,intmaxsize StackT, maxsize::~Stack() {delete[] m_pT ;}templateclassT,intmaxsizevoidStackT, maxsize::push(T t) {m_size;m_pT[m_size - 1] t;}templateclassT,intmaxsize T StackT, maxsize::pop() {T t m_pT[m_size - 1];m_size--;returnt;}templateclassT,intmaxsizeboolStackT, maxsize::isEmpty() {returnm_size 0;}使用示例如下:1234567891011121314//main.cpp#include stdio.h#include stack.hintmain() {intmaxsize 1024;Stackint,1024 intStack;for(inti 0; i maxsize; i) {intStack.push(i);}while(!intStack.isEmpty()) {printf(num:%d\n, intStack.pop());}return0;}模板专门化当我们要定义模板的不同实现我们可以使用模板的专门化。例如我们定义的stack类模板如果是char*类型的栈我们希望可以复制char的所有数据到stack类中因为只是保存char指针char指针指向的内存有可能会失效stack弹出的堆栈元素char指针指向的内存可能已经无效了。还有我们定义的swap函数模板在vector或者list等容器类型时如果容器保存的对象很大会占用大量内存性能下降因为要产生一个临时的大对象保存a这些都需要模板的专门化才能解决。函数模板专门化假设我们swap函数要处理一个情况我们有两个很多元素的vectorint,在使用原来的swap函数执行tmpT t1要拷贝t1的全部元素占用大量内存造成性能下降于是我们系统通过vector.swap函数解决这个问题,代码如下:1234//method.htemplateclassTvoidswap(T t1, T t2);#include method.cpp123456789101112#include vectorusingnamespacestd;templateclassTvoidswap(T t1, T t2) {T tmpT;tmpT t1;t1 t2;t2 tmpT;}templatevoidswap(std::vectorint t1, std::vectorint t2) {t1.swap(t2);}template前缀表示这是一个专门化,描述时不用模板参数使用示例如下:123456789101112131415161718192021222324//main.cpp#include stdio.h#include vector#include string#include method.hintmain() {usingnamespacestd;//模板方法string str1 1, str2 2;swap(str1, str2);printf(str1:%s, str2:%s\n, str1.c_str(), str2.c_str());vectorint v1, v2;v1.push_back(1);v2.push_back(2);swap(v1, v2);for(inti 0; i v1.size(); i) {printf(v1[%d]:%d\n, i, v1[i]);}for(inti 0; i v2.size(); i) {printf(v2[%d]:%d\n, i, v2[i]);}return0;}vectorint的swap代码还是比较局限如果要用模板专门化解决所有vector的swap该如何做呢只需要把下面代码123templatevoidswap(std::vectorint t1, std::vectorint t2) {t1.swap(t2);}改为123templateclassVvoidswap(std::vectorV t1, std::vectorV t2) {t1.swap(t2);}就可以了其他代码不变。类模板专门化请看下面compare代码:12345678910//compare.htemplateclassTclasscompare{public:boolequal(T t1, T t2){returnt1 t2;}};12345678910111213#include iostream#include compare.hintmain(){usingnamespacestd;charstr1[] Hello;charstr2[] Hello;compareint c1;comparechar* c2;cout c1.equal(1, 1) endl;//比较两个int类型的参数cout c2.equal(str1, str2) endl;//比较两个char *类型的参数return0;}在比较两个整数compare的equal方法是正确的但是compare的模板参数是char*时这个模板就不能工作了于是修改如下:123456789101112131415161718192021//compare.h#include string.htemplateclassTclasscompare{public:boolequal(T t1, T t2){returnt1 t2;}};templateclasscomparechar*{public:boolequal(char* t1,char* t2){returnstrcmp(t1, t2) 0;}};main.cpp文件不变此代码可以正常工作。模板类型转换还记得我们自定义的Stack模板吗在我们的程序中假设我们定义了Shape和Circle类代码如下:123456//shape.hclassShape {};classCircle :publicShape {};然后我们希望可以这么使用:1234567891011//main.cpp#include stdio.h#include stack.h#include shape.hintmain() {StackCircle* pcircleStack;StackShape* pshapeStack;pcircleStack.push(newCircle);pshapeStack pcircleStack;return0;}这里是无法编译的因为StackShape*不是StackCircle*的父类然而我们却希望代码可以这么工作那我们就要定义转换运算符了Stack代码如下:12345678910111213141516//statck.htemplateclassTclassStack {public:Stack();~Stack();voidpush(T t);T pop();boolisEmpty();templateclassT2 operator StackT2();private:T *m_pT;intm_maxSize;intm_size;};#include stack.cpp123456789101112131415161718192021222324252627282930templateclassT StackT::Stack(){m_maxSize 100;m_size 0;m_pT newT[m_maxSize];}templateclassT StackT::~Stack() {delete[] m_pT ;}templateclassTvoidStackT::push(T t) {m_size;m_pT[m_size - 1] t;}templateclassT T StackT::pop() {T t m_pT[m_size - 1];m_size--;returnt;}templateclassTboolStackT::isEmpty() {returnm_size 0;}templateclassTtemplateclassT2 StackT::operator StackT2() {StackT2 StackT2;for(inti 0; i m_size; i) {StackT2.push((T2)m_pT[m_size - 1]);}returnStackT2;}1234567891011//main.cpp#include stdio.h#include stack.h#include shape.hintmain() {StackCircle* pcircleStack;StackShape* pshapeStack;pcircleStack.push(newCircle);pshapeStack pcircleStack;return0;}这样StackCircle或者StackCircle*就可以自动转换为StackShape或者StackShape*,如果转换的类型是Stackint到StackShape编译器会报错。其他一个类没有模板参数但是成员函数有模板参数是可行的代码如下:12345678910111213classUtil {public:templateclassTboolequal(T t1, T t2) {returnt1 t2;}};intmain() {Util util;inta 1, b 2;util.equalint(1, 2);return0;}甚至可以把Util的equal声明为static,代码如下:123456789101112classUtil {public:templateclassTstaticboolequal(T t1, T t2) {returnt1 t2;}};intmain() {inta 1, b 2;Util::equalint(1, 2);return0;}以上就是本文的全部内容希望对大家的学习有所帮助