阿里云服务器上做网站,动易做网站,蚌埠哪有做网站的,郑州做网站华久科技引言 模板#xff08;Template#xff09;指C程序设计设计语言中采用类型作为参数的程序设计#xff0c;支持通用程序设计。C 的标准库提供许多有用的函数大多结合了模板的观念#xff0c;如STL以及IO Stream。 函数模板 在c入门中#xff0c;很多人会接触swap(int, … 引言 模板Template指C程序设计设计语言中采用类型作为参数的程序设计支持通用程序设计。C 的标准库提供许多有用的函数大多结合了模板的观念如STL以及IO Stream。 函数模板 在c入门中很多人会接触swap(int, int)这样的函数类似代码如下: void swap(inta , int b) {int temp a;a b;b temp;
} 但是如果是要支持long,string,自定义class的swap函数,代码和上述代码差不多只是类型不同这个时候就是我们定义swap的函数模板,就可以复用不同类型的swap函数代码函数模板的声明形式如下: template class identifier function_declaration;
template typename identifier function_declaration; swap函数模板的声明和定义代码如下: //method.h
templatetypename T void swap(T t1, T t2);#include method.cpp //method.cpptemplatetypename T void swap(T t1, T t2) {T tmpT;tmpT t1;t1 t2;t2 tmpT;
} 上述是模板的声明和定义了那模板如何实例化呢模板的实例化是编译器做的事情与程序员无关那么上述模板如何使用呢代码如下: //main.cpp
#include stdio.h
#include method.h
int main() {//模板方法 int num1 1, num2 2;swapint(num1, num2);printf(num1:%d, num2:%d\n, num1, num2); return 0;
} 这里使用swap函数必须包含swap的定义否则编译会出错这个和一般的函数使用不一样。所以必须在method.h文件的最后一行加入#include method.cpp。 类模板 考虑我们写一个简单的栈的类这个栈可以支持int类型long类型string类型等等不利用类模板我们就要写三个以上的stack类其中代码基本一样通过类模板我们可以定义一个简单的栈模板再根据需要实例化为int栈long栈string栈。 //statck.h
template class T class Stack {public:Stack();~Stack();void push(T t);T pop();bool isEmpty();private:T *m_pT; int m_maxSize;int m_size;
};#include stack.cpp //stack.cpp
template class T StackT::Stack(){m_maxSize 100; m_size 0;m_pT new T[m_maxSize];
}
template class T StackT::~Stack() {delete [] m_pT ;
}template class T void StackT::push(T t) {m_size;m_pT[m_size - 1] t;}
template class T T StackT::pop() {T t m_pT[m_size - 1];m_size--;return t;
}
template class T bool StackT::isEmpty() {return m_size 0;
} 上述定义了一个类模板--栈这个栈很简单只是为了说明类模板如何使用而已最多只能支持100个元素入栈使用示例如下: //main.cpp
#include stdio.h
#include stack.h
int main() {Stackint intStack;intStack.push(1);intStack.push(2);intStack.push(3);while (!intStack.isEmpty()) {printf(num:%d\n, intStack.pop());}return 0;
} 模板参数 模板可以有类型参数也可以有常规的类型参数int也可以有默认模板参数例如 templateclass T, T def_val class Stack{...} 上述类模板的栈有一个限制就是最多只能支持100个元素我们可以使用模板参数配置这个栈的最大元素数,如果不配置就设置默认最大值为100代码如下: //statck.h
template class T,int maxsize 100 class Stack {public:Stack();~Stack();void push(T t);T pop();bool isEmpty();private:T *m_pT; int m_maxSize;int m_size;
};#include stack.cpp //stack.cpp
template class T,int maxsize StackT, maxsize::Stack(){m_maxSize maxsize; m_size 0;m_pT new T[m_maxSize];
}
template class T,int maxsize StackT, maxsize::~Stack() {delete [] m_pT ;
}template class T,int maxsize void StackT, maxsize::push(T t) {m_size;m_pT[m_size - 1] t;}
template class T,int maxsize T StackT, maxsize::pop() {T t m_pT[m_size - 1];m_size--;return t;
}
template class T,int maxsize bool StackT, maxsize::isEmpty() {return m_size 0;
} 使用示例如下: //main.cpp
#include stdio.h
#include stack.h
int main() {int maxsize 1024;Stackint,1024 intStack;for (int i 0; i maxsize; i) {intStack.push(i);}while (!intStack.isEmpty()) {printf(num:%d\n, intStack.pop());}return 0;
} 模板专门化 当我们要定义模板的不同实现我们可以使用模板的专门化。例如我们定义的stack类模板如果是char*类型的栈我们希望可以复制char的所有数据到stack类中因为只是保存char指针char指针指向的内存有可能会失效stack弹出的堆栈元素char指针指向的内存可能已经无效了。还有我们定义的swap函数模板在vector或者list等容器类型时如果容器保存的对象很大会占用大量内存性能下降因为要产生一个临时的大对象保存a这些都需要模板的专门化才能解决。 函数模板专门化 假设我们swap函数要处理一个情况我们有两个很多元素的vectorint,在使用原来的swap函数执行tmpT t1要拷贝t1的全部元素占用大量内存造成性能下降于是我们系统通过vector.swap函数解决这个问题,代码如下: //method.h
templateclass T void swap(T t1, T t2);#include method.cpp #include vector
using namespace std;
templateclass T void swap(T t1, T t2) {T tmpT;tmpT t1;t1 t2;t2 tmpT;
}template void swap(std::vectorint t1, std::vectorint t2) {t1.swap(t2);
} template前缀表示这是一个专门化,描述时不用模板参数使用示例如下: //main.cpp
#include stdio.h
#include vector
#include string
#include method.h
int main() {using namespace std;//模板方法 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 (int i 0; i v1.size(); i) {printf(v1[%d]:%d\n, i, v1[i]);}for (int i 0; i v2.size(); i) {printf(v2[%d]:%d\n, i, v2[i]);}return 0;
} vectorint的swap代码还是比较局限如果要用模板专门化解决所有vector的swap该如何做呢只需要把下面代码 template void swap(std::vectorint t1, std::vectorint t2) {t1.swap(t2);
} 改为 templateclass V void swap(std::vectorV t1, std::vectorV t2) {t1.swap(t2);
} 就可以了其他代码不变。 类模板专门化 请看下面compare代码: //compare.h
template class Tclass compare{public:bool equal(T t1, T t2){return t1 t2;}
}; #include iostream
#include compare.hint main(){using namespace std;char str1[] Hello;char str2[] Hello;compareint c1;comparechar * c2; cout c1.equal(1, 1) endl; //比较两个int类型的参数cout c2.equal(str1, str2) endl; //比较两个char *类型的参数return 0;} 在比较两个整数compare的equal方法是正确的但是compare的模板参数是char*时这个模板就不能工作了于是修改如下: //compare.h
#include string.h
template class Tclass compare{public:bool equal(T t1, T t2){return t1 t2;}
};templateclass comparechar *
{
public:bool equal(char* t1, char* t2){return strcmp(t1, t2) 0;}
}; main.cpp文件不变此代码可以正常工作。 模板类型转换 还记得我们自定义的Stack模板吗在我们的程序中假设我们定义了Shape和Circle类代码如下: //shape.h
class Shape {};
class Circle : public Shape {
}; 然后我们希望可以这么使用: //main.cpp
#include stdio.h
#include stack.h
#include shape.h
int main() {StackCircle* pcircleStack;StackShape* pshapeStack;pcircleStack.push(new Circle);pshapeStack pcircleStack;return 0;
} 这里是无法编译的因为StackShape*不是StackCircle*的父类然而我们却希望代码可以这么工作那我们就要定义转换运算符了Stack代码如下: //statck.h
template class T class Stack {public:Stack();~Stack();void push(T t);T pop();bool isEmpty();templateclass T2 operator StackT2();private:T *m_pT; int m_maxSize;int m_size;
};#include stack.cpp template class T StackT::Stack(){m_maxSize 100; m_size 0;m_pT new T[m_maxSize];
}
template class T StackT::~Stack() {delete [] m_pT ;
}template class T void StackT::push(T t) {m_size;m_pT[m_size - 1] t;}
template class T T StackT::pop() {T t m_pT[m_size - 1];m_size--;return t;
}
template class T bool StackT::isEmpty() {return m_size 0;
}template class T template class T2 StackT::operator StackT2() {StackT2 StackT2;for (int i 0; i m_size; i) {StackT2.push((T2)m_pT[m_size - 1]);}return StackT2;
} //main.cpp
#include stdio.h
#include stack.h
#include shape.h
int main() {StackCircle* pcircleStack;StackShape* pshapeStack;pcircleStack.push(new Circle);pshapeStack pcircleStack;return 0;
} 这样StackCircle或者StackCircle*就可以自动转换为StackShape或者StackShape*,如果转换的类型是Stackint到StackShape编译器会报错。 其他 一个类没有模板参数但是成员函数有模板参数是可行的代码如下: class Util {public:template class T bool equal(T t1, T t2) {return t1 t2;}
};int main() {Util util;int a 1, b 2;util.equalint(1, 2);return 0;
} 甚至可以把Util的equal声明为static,代码如下: class Util {public:template class T static bool equal(T t1, T t2) {return t1 t2;}
};int main() {int a 1, b 2;Util::equalint(1, 2);return 0;
}