定义:函数模板不是一个实在的函数,编译器不能为其生成可执行代码。定义函数模板后只是一个对函数功能框架的描述,当它具体执行时,将根据传递的实际参数决定其功能
为了交换两个整型变量的值,需要写下面的 Swap 函数:
void Swap(int & x, int & y)
{
int tmp = x;
x = y;
y = tmp;
}
为了交换两个 double 型变量的值,还需要编写下面的 Swap 函数:
void Swap (double & xr double & y)
{
double tmp = x;
x = y;
y = tmp;
}
如果还要交换两个 char 型变量的值需要再编写 Swap 函数。而这些 Swap 函数除了处理的数据类型不同外,形式上都是一样的。能否只写一遍 Swap 函数,就能用来交换各种类型的变量的值呢?继承和多态显然无法解决这个问题。因此,“模板”的概念就应运而生了。
1.1 一般模板函数写法如下:
template返回值类型 模板名(形参表) { 函数体 }
class也可以换成typename,如下:
template
模板函数看上去就像函数,Swap函数如下:
templatevoid Swap(T & x, T & y) { T tmp = x; x = y; y = tmp; }
T 是类型参数,代表类型。编译器由模板自动生成函数时,会用具体的类型名对模板中所有的类型参数进行替换,其他部分则原封不动地保留。同一个类型参数只能替换为同一种类型。编译器在编译到调用函数模板的语句时,会根据实参的类型判断该如何替换模板中的类型参数。
1.2 特化模板函数使用模板时会遇到一些特殊的类型需要特殊处理,不能直接使用当前的模板函数,所以此时我们就需要对该类型特化出一个模板函数(就是写出一个模板函数专门给该类型使用)
一个判断相等的函数:
templatebool Isequal(T& p1, T& p2){ return p1 == p2; }
但是该模板函数在对于字符串进行比较时就不能使用了,对于字符串我们不能直接比较,因此直接特化出一个专门供字符串使用的模板参数
template<> // 此处不添加类型模板,直接使用空即可 bool Isequal(char*& p1, char*& p2){ return strcmp(p1, p2) == 0; }
【注意】
-
使用模板特化时,必须要先有基础的模板函数(就是上面第一个模板函数)
-
使用特换模板函数时格式有要求:
1.template 后直接跟<> 里面不用写类型
2.函数名<特化类型>(特化类型 参数1, 特化类型 参数2 , …) 在函数名后跟<>其中写要特化的类型 -
特化的函数的函数名,参数列表要和原基础的模板函数想相同,避免不必要的错误
队列(queue)是先进先出的数据结构,存储方式可以是数组也可以是链表。如果用数组存储,一般采用循环队列的方式。
所以需记住几个关键点:
队头指针进1:front = (front+1)%maxsize
队尾指针进1:rear = (rear+1)%maxsize
判断队空:front = rear
判断队满:front = (rear+1)%maxsize,这里,队满的时候队尾和队头之间空有一个元素,以此来避免和front=rear混淆
定义头文件
#include #includeusing namespace std; template class SeqQueue{ public: SeqQueue(int sz=50); ~SeqQueue(); bool EnQueue(const T& x); bool DeQueue(); T getFront(); //获取队头元素 bool makeEmpty(){front = rear =0; return true;} bool isEmpty()const{return (front==rear)?true:false;} bool isFull()const{return ((rear+1)%maxsize==front)?true:false;} int getsize()const{return (rear-front+maxsize)%maxsize;} //获取队列元素个数 private: int front,rear; T* element; int maxsize; };
成员函数的实现
#include "queue.h" template1.2 模板类StackSeqQueue ::SeqQueue(int sz):maxsize(sz):front(0):rear(0){ element = new T[maxsize]; assert(element!=NULL); } template bool SeqQueue ::EnQueue(const T& x){ if(isFull()==true)return false; element[rear]=x; rear = (rear+1)%maxsize; return true; } template bool SeqQueue ::DeQueue(){ if(isEmpty()==true)return false; T x = element[front]; front = (front+1)%maxsize; delete x; return true; } template T SeqQueue ::getFront(){ if(isEmpty()==true)return -1; return element[front]; }
头文件
#include #includeusing namespace std; const int stackIncreament=20; template class SeqStack{ public: SeqStack(int sz = 50); ~SeqStack(); bool push(const T& x); bool pop(const T& x); bool isFull()const{return (top == maxsize-1)?true:false;} bool isEmpty()const{return (top ==-1)?true:false;} int getsize(){return top+1;} T gettop(); void makeEmpty(){top = -1;} private: T * element; int maxsize; int top; void overflowProcess(); };
成员函数实现
#include "queue.h" template1.3 模板特化SeqQueue ::SeqQueue(int sz):maxsize(sz):front(0):rear(0){ element = new T[maxsize]; assert(element!=NULL); } template bool SeqQueue ::EnQueue(const T& x){ if(isFull()==true)return false; element[rear]=x; rear = (rear+1)%maxsize; return true; } template bool SeqQueue ::DeQueue(){ if(isEmpty()==true)return false; T x = element[front]; front = (front+1)%maxsize; delete x; return true; } template T SeqQueue ::getFront(){ if(isEmpty()==true)return -1; return element[front]; }
1.3.1.1 函数模板
templatevoid Swap(T& left, T& right) { T temp = left; left = right; right = temp; } template T add(T a, T b) { return a + b; } template T2 Add(const T1& a, const T2& b) { return a + b; } int Add(const int& a, const int& b) { return a + b; }
1.3.1.2 函数模板特化
函数模板 template1.3.2 类模板及特化T Add(T& a, T& b) { return a + b; } 函数模板的特化 template <> char* Add (char*& a, char*& b) { strcat(a, b); return a; } 普通函数 char* Add(char*& a, char*& b) { strcat(a, b); return a; }
1.3.2.1 类模板
templateclass Date { public: Date(T1 year, T2 month, T3 day) :_year(year) , _month(month) , _day(day) {} void Display(); private: T1 _year; T2 _month; T3 _day; };
1.3.2.2 类模板特化
特化之前需要存在基础类模板 template三.类模板模拟智能指针auto_ptrclass A { public: A() { cout << "A(T1, T2)" << endl; } private: T1 _t1; T2 _t2; }; 全特化--> 所有的参数都为具体类型 template <> class A { public: A() { cout << "A(int, char)" << endl; } private: int _t1; char _t2; }; 偏特化: a. 部分特化 template class A { public: A() { cout << "A(T1, double)" << endl; } private: T1 _t1; double _t2; }; template class A { public: A() { cout << "A(T1, char)" << endl; } private: T1 _t1; double _t2; }; b. 对模板参数做进一步的限制 template class A { public: A() { cout << "A(T1&, T2&>" << endl; } };
#includeusing namespace std; template class autoptr{ T* p; public: autoptr(T* p=0):p(p){} ~autoptr(){delete p;} autoptr(autoptr& a):p(0){operator=(a);} //autoptr(autoptr& a){operator=(a);}//错误的拷贝构造函数,p没有初始化,将是野指针,会delete出错 autoptr& operator=(autoptr& a){ if(this==&a) return *this; if(p!=NULL) { //cout << "free previous memoryn"; delete p; } p = a.p; a.p = NULL; return *this; } T& operator*()const{return *p;} T* operator->()const{return p;} }; class A{ int data; public: A(int d):data(d){cout< show(); autoptr q(p); //p->show();出错,p已经没有动态内存的所有权了 q->show(); autoptr r(new A(20)); (*r).show(); r = q; r->show(); (*r).show(); autoptr x; x=r; (*x).show(); }
运行结果



