模板
模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。模板是创建泛型类或函数的蓝图或公式。
函数模板
模板函数定义的一般形式如下所示:
//定义
template<class Type>
int compare(const Type& v1, const Type& v2)
{
if(v1<v2) return -1;
if(v1>v2) return 1;
return 0;
}
//调用
const char* cp1 = "world", *cp2="hi";
int i1=1,i2=2;
compare(i1,i2);
compare(cp1,cp2);
一般模板函数与特化模板函数
以compare函数举例
//一般模板函数
template<class Type>
int compare(const Type& v1, const Type& v2)
{
if(v1<v2) return -1;
if(v1>v2) return 1;
return 0;
}
//特化模板函数
template<>
int compare<const char*>(const char * const &v1, const char * const &v2)
{
return strcmp(v1,v2);
}
特化函数与模板函数的区别:
(1)、模板函数的T参数只能传入类类型的参数;特化函数的参数只能传入对应的参数类型,基本类型或类类型。
(2)、模板函数在link时检查类型,编译时只是当成了注释;特化函数及参数在编译时检查是否匹配或有错。
(3)、特化函数与模板函数重名时,特化函数需要加特殊处理。一种方式是加inline修饰,不在编译时生成对应的符号表。
类模板
template<class Type> class Queue;
template<class Type> class QueueItem{
QueueItem(const Type &t):item(t), next(0){}
Type item;
QueueItem * next;
friend class Queue<Type>;
friend ostream& operator<<(ostream& os, const Queue<Type> &q);
};
成员模板函数
声明了类模板后,就可以将类型参数用于类的成员函数和成员变量,即原来使用 int、float、char 等内置类型的地方都可以用类型参数来代替。
#include <iostream>
using namespace std;
class Printer
{
public:
template<typename T>//类的成员函数是模板
void print(const T& t)
{
cout << t << endl;
}
template<typename T>
void print(int a, const T& t)
{
cout << a << t << endl;
}
};
int main()
{
Printer p;
p.print<const char*>("abc"); //类成员函数是模板的调用方式
p.print("abc"); //编译器推断参数模板类型
p.print(2, "abc"); //类模板成员函数重载
getchar();
return 0;
}
模板特化
模板函数特化
使用模板时会遇到一些特殊的类型需要特殊处理,不能直接使用当前的模板函数,所以此时我们就需要对该类型特化出一个模板函数(就是写出一个模板函数专门给该类型使用)
template<>
void Queue<const char*>::push(const char * const &val){
char* new_item = new char[strlen(val)+1];
strncpy(new_item,val,strlen(val)+1);
QueueItem<const char*> * pt = new QueueItem<const char*>(new_item);
if(empty()){
head=tail=pt;
}else{
tail->next = pt;
tail = pt;
}
}
template<>
void Queue<const char*>::pop(){
QueueItem<const char*> * p = head;
delete head->item;
head = head->next;
delete p;
}
模板成员函数特化
当函数模板需要对某些类型进行特化处理,称为函数模板的特化。
template<>
void Queue<const char*>::push(const char * const &val){
char* new_item = new char[strlen(val)+1];
strncpy(new_item,val,strlen(val)+1);
QueueItem<const char*> * pt = new QueueItem<const char*>(new_item);
if(empty()){
head=tail=pt;
}else{
tail->next = pt;
tail = pt;
}
}
template<>
void Queue<const char*>::pop(){
QueueItem<const char*> * p = head;
delete head->item;
head = head->next;
delete p;
}
模板类特化
类模板的特化:与函数模板类似,当类模板内需要对某些类型进行特别处理时,使用类模板的特化。
在模板类里,所有的类型都是模板,当我们将所有的模板类型T都明确化,并且写了一个类名与主模板类名相同的类,那么这个类就叫做全特化类。偏特化就是介于二者之间的模板。
//模板类
template<typename T, class N> class Test_Class
{
public:
static bool comp(T num1, N num2)
{
return (num1<num2)?true:false;
}
};
//偏特化,模板类
template<class N> class Test_Class<int, N>
{
public:
static bool comp(int num1, N num2)
{
return (num1<num2)?true:false;
}
};
//全特化
template<>
class Queue<const char*>{
public:
void Push(const char* str){real_queue.push(str);}
void Pop(){real_queue.pop();}
bool isEmpty() {return real_queue.empty();}
string front() const {return real_queue.front();}
friend ostream & operator<<(ostream& os, Queue<const char*> &que){
os<<que.real_queue;
}
// const string &front() const{return real_queue.front();}
private:
Queue<string> real_queue;
};
模板类(AutoPtr)
AutoPtr定义了类似指针的对象,将 new 获得的地址赋给该对象。当AutoPtr对象过期时,析构函数将使用 delete 来释放内存。如果将 new 返回的地址赋值给 AutoPtr对象,无须记住还需要释放这些内存。在 AutoPtr 对象过期时,内存将自动被释放。
构造函数
template<class T>
AutoPtr<T>::AutoPtr(T* pData)
{
m_pData = pData;
m_nUser = new int(1);
}
析构函数
template<class T>
AutoPtr<T>::~AutoPtr()
{
decrUser();
}
template<class T>
void AutoPtr<T>::decrUser()
{
--(*m_nUser);
if((*m_nUser)==0){
delete m_pData;
m_pData = 0;
delete m_nUser;
m_nUser = 0;
}
}
拷贝构造函数
AutoPtr<T>& AutoPtr<T>::operator=(const AutoPtr<T>& h)
{
decrUser();
m_pData = h.m_pData;
m_nUser = h.m_nUser;
(*m_nUser)++;
}
等号、->、*等运算符重载
public:
T* operator->(){
return m_pData;
}
T& operator*(){
return *m_pData;
}
const T& operator *() const{
return *m_pData;
}
const T* operator ->() const{
return m_pData;
}
AutoPtr<T>& AutoPtr<T>::operator=(const AutoPtr<T>& h)
{
if(this==&h) return *this;
decrUser();
m_pData = h.m_pData;
m_nUser = h.m_nUser;
(*m_nUser)++;
return *this;
}
主函数调用AutoPtr
int *a = new int(3);
int *b = new int(7);
AutoPtr<int> p(b);//建一个智能指针和b指向同个地方
AutoPtr<int> t(p);//拷贝构造函数的使用
AutoPtr<int> f(a);
cout<<"p:"<<*p<<endl;
cout<<"t:"<<*t<<endl;
p=f;
cout<<"p:"<<*p<<endl;