一、模板函数(compare)
所谓函数模板,实际上是建立一个通用函数,它所用到的数据的类型(包括返回值类型、形参类型、局部变量类型)可以不具体指定,而是用一个虚拟的类型来代替(实际上是用一个标识符来占位),等发生函数调用时再根据传入的实参来逆推出真正的类型。这个通用函数就称为函数模板(Function Template)。
在函数模板中,数据的值和类型都被参数化了,发生函数调用时编译器会根据传入的实参来推演形参的值和类型。换个角度说,函数模板除了支持值的参数化,还支持类型的参数化。
一但定义了函数模板,就可以将类型参数用于函数定义和函数声明了。说得直白一点,原来使用 int、float、char 等内置类型的地方,都可以用类型参数来代替。
1.一般模板函数
添加以下代码到queue.h
template<class Type>
int compare(const Type& v1, const Type& v2)
{
if(v1<v2) return -1;
if(v1>v2) return 1;
return 0;
}
添加以下代码到queue.cpp
void testTemplate()
{
double a = 1.2;
double b = 1.5;
cout<<"a=1.2,b=1.5,a<b:"<<compare(a,b)<<endl;
double a1=3.0;
double b1=2.0;
cout<<"a1=3.0,b1=2.0,a1>b1:"<<compare(a1,b1)<<endl;
}
int main(){
testTemplate();
return 0;
}
运行结果:
2.特化模板函数
有时通用的函数模板不能解决个别类型的问题,我们必须对此进行定制,这就是函数模板的特化。 添加以下代码到queue.h
template<>
int compare<const char*>(const char * const &v1, const char * const &v2);
添加以下代码到queue.cpp
template<>
int compare<const char*>(const char * const &v1, const char * const &v2)
{
return strcmp(v1,v2);
}
void testTemplate()
{
char str[10];
char str1[10];
strcpy(str,"abc");
strcpy(str1,"def");
cout<<"compare abc,def: "<<compare<const char*>(str,str1)<<endl;
cout<<"compare def,abc "<<compare<const char*>(str1,str)<<endl;
}
int main(){
testTemplate();
return 0;
}
运行结果:
二、模板类Queue或Stack
C++ 中类模板的写法如下:
template <类型参数表>
class 类模板名{
成员函数和成员变量
};
类型参数表的写法如下:
class类塑参数1, class类型参数2, ...
1.模板类(Queue,Stack)
添加以下代码到queue.h
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);
public:
QueueItem<Type>* operator++(){
return next;
}
Type & operator*(){
return item;
}
};
template<class Type>
class Queue
{
public:
Queue():head(0),tail(0){}
Queue(const Queue& q):head(0),tail(0){
copy_items(q);
}
template<class It>
Queue(It beg, It end):head(0),tail(0){copy_items(beg,end);}
template<class It>
void assign(It beg, It end);
Queue& operator=(const Queue&);
~Queue(){destroy();}
Type& front() {return head->item;}
const Type& front() const{return head->item;}
void push(const Type &);
void pop();
bool empty() const{return head==0;}
friend ostream& operator<<(ostream& os, const Queue<Type> &q){
QueueItem<Type> * p;
for(p=q.head;p;p=p->next){
os<<p->item<<" ";
}
return os;
}
const QueueItem<Type>* Head() const{return head;}
const QueueItem<Type>* End() const{return (tail==NULL)?NULL:tail->next;}
private:
QueueItem<Type> * head;
QueueItem<Type> * tail;
void destroy();
void copy_items(const Queue &);
template<class It> void copy_items(It beg,It end);
};
2.成员模板函数
类模板中的成员函数放到类模板定义外面写时的语法如下:
template <类型参数表>
返回值类型 类模板名<类型参数名列表>::成员函数名(参数表)
{
...
}
用类模板定义对象的写法如下:
类模板名<真实类型参数表> 对象名(构造函数实际参数表);
如果类模板有无参构造函数,那么也可以使用如下写法:
类模板名 <真实类型参数表> 对象名;
添加以下代码到queue.h
template<class Type>
void Queue<Type>::destroy()
{
while (!empty()) {
pop();
}
}
template<class Type>
void Queue<Type>::pop(){
if(head==0) return;
QueueItem<Type> * p = head;
head = head->next;
delete p;
}
template<class Type>
void Queue<Type>::push(const Type& val){
QueueItem<Type> * pt = new QueueItem<Type>(val);
if(empty()){
head = tail = pt;
}else{
tail->next = pt;
tail = pt;
}
}
template<>
void Queue<const char*>::push(const char * const &val);
template<>
void Queue<const char*>::pop();
template<class Type>
void Queue<Type>::copy_items(const Queue &orig){
for(QueueItem<Type> *pt = orig.head;pt;pt=pt->next){
push(pt->item);
}
}
template<class Type>
Queue<Type>& Queue<Type>::operator=(const Queue& q)
{
destroy();
copy_items(q);
}
template<class Type> template<class It> void Queue<Type>::assign(It beg, It end)
{
destroy();
copy_items(beg,end);
}
template<class Type> template<class It> void Queue<Type>::copy_items(It beg,It end)
{
while(beg!=end){
push(*beg);
++beg;
}
}
3.模板特化:模板函数特化、模板成员函数特化、模板类特化
C++中的模板特化不同于模板的实例化,模板参数在某种特定类型下的具体实现称为模板的特化。模板特化有时也称之为模板的具体化,分别有函数模板特化和类模板特化。 模板成员函数特化: 添加以下代码到queue.h
template<class Type>
void Queue<Type>::pop(){
if(head==0) return;
QueueItem<Type> * p = head;
head = head->next;
delete p;
}
template<class Type>
void Queue<Type>::push(const Type& val){
QueueItem<Type> * pt = new QueueItem<Type>(val);
if(empty()){
head = tail = pt;
}else{
tail->next = pt;
tail = pt;
}
}
template<>
void Queue<const char*>::push(const char * const &val);
template<>
void Queue<const char*>::pop();
模板类特化: 添加以下代码到queue.cpp
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;
}
实现 添加以下代码到queue.cpp
void testTemplate()
{
Queue<int> qt;
double d = 3.3;
qt.push(1);
qt.push(d);
qt.push(10);
cout<<qt<<endl;
short data[5] = {0,3,6,9};
Queue<int> qi(data,data+5);
cout<<qi<<endl;
while(!qi.empty())
{
cout<<qi.front()<<" ";
qi.pop();
}
vector<int> vi(data,data+5);
qi.assign(vi.begin(),vi.end());
cout<<endl;
cout<<qi;
Queue<const char*> qst;
char str[10];
strcpy(str,"I am");
qst.push(str);
strcpy(str,"03");
qst.push(str);
strcpy(str,"huang");
qst.push(str);
cout<<endl<<qst<<endl;
}
int main(){
testTemplate();
return 0;
}
运行结果:
三、模板类AutoPtr
智能指针的一种通用实现技术是使用引用计数。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象的指针指向同一对象。智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏。
1.构造函数
添加以下代码到autoptr.h
template<class T>
class AutoPtr
{
public:
AutoPtr(T* pData);
};
template<class T>
AutoPtr<T>::AutoPtr(T* pData)
{
m_pData = pData;
m_nUser = new int(1);
}
2.析构函数
添加以下代码到autoptr.h
template<class T>
class AutoPtr
{
public:
AutoPtr(T* pData);
~AutoPtr();
};
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;
}
}
3.拷贝构造函数
添加以下代码到autoptr.h
template<class T>
class AutoPtr
{
public:
AutoPtr(T* pData);
AutoPtr(const AutoPtr<T>& h);
AutoPtr<T>& operator=(const AutoPtr<T>& h);
~AutoPtr();
};
template<class T>
AutoPtr<T>::AutoPtr(const AutoPtr<T>& h)
{
m_pData = h.m_pData;
m_nUser = h.m_nUser;
(*m_nUser)++;
}
template<class T>
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;
}
4.等号、->、*等运算符重载
添加以下代码到autoptr.h
template<class T>
class AutoPtr
{
public:
AutoPtr(T* pData);
AutoPtr(const AutoPtr<T>& h);
AutoPtr<T>& operator=(const AutoPtr<T>& h);
~AutoPtr();
T* operator->(){
return m_pData;
}
T& operator*(){
return *m_pData;
}
const T& operator *() const{
return *m_pData;
}
const T* operator ->() const{
return m_pData;
}
private:
void decrUser();
T * m_pData;
int * m_nUser;
};
5.主函数调用AutoPtr
添加以下代码到main.cpp。 CMatrix.h ,CMatrix.cpp自行添加到文件夹中
#include "autoptr.h"
#include "cmatrix.h"
void TestAutoPtr()
{
AutoPtr<CMatrix>h1(new CMatrix);
double data[6] = {1,2,3,4,5,6};
h1->Create(2,3,data);
cout<<*h1<<endl;
AutoPtr<CMatrix> h2(h1);
(*h2).Set(0,1,10);
cout<<*h1<<endl<<*h2<<endl;
}
int main(){
TestAutoPtr();
return 0;
}
运行结果:
|