模板是C++的高级特性,掌握模板的使用,将大大提升C++的开发效率,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型,模板分为两大类,即函数模板、类模板,C++已经为我们提供了标准模板库(STL),在定义模板时,经常看到template,它为模板关键字,尖括号’<>'中为模板参数,模板参数主要由两种,一种是模板类型参数,例如int 、float,一种是模板非类型参数,通常为一个常数,也可以直接指定一个默认常量。
1、函数模板
函数模板针对仅参数类型不同的函数,且不能在函数体内定义一个函数模板,模板形参不能为空,否则模板将无任何意义。
定义形式如下:
template <class T>
返回类型 函数名(函数形参)
{
;/*函数体*/
}
例如:
template <class T,int len=0>
T min(T a[len])
{
T tmp;
int i = 0;
tmp = a[0];
for(i = 0;i < len;i++)
{
if(tmp > a[i])
{
tmp = a[i];
}
}
return tmp;
}
int main()
{
float a[5] = {88.2, 7.8, 95.4, 12.0, 5.1};
float minum = min<float,5>(a);
cout<<"min num == "<<minum<<endl;
cin.get();
cin.get();
return 0;
}
2、类模板
类模板代表一簇类,它使类中的一些数据成员及成员函数的参数或返回值可以直接取任意数据类型,类模板不是一个真实的类,需要实例化,它的一般定义格式如下:
template<class T>
class A{
public:
T func(T a,T b);
};
类的实例化可以是: A<int> a;
3、模板参数
有三种类型的模板形参:类型形参,非类型形参和模板形参。
- 类型模板形参:类型形参由关见字class或typename后接说明符构成,如template void h(T a){};其中T就是一个类型形参,类型形参的名字由用户自已确定。模板形参表示的是一个未知的类型。一种模板形参只能表示一种类型,也可以指定一个默认类型,例如:template void h(T a){};。
- 非类型模板形参: 非类型形参在模板定义的内部是常量值,也因此调用非类型模板形参的实参必须是一个常量表达式,即它必须能在编译时计算出结果,因此任何局部对象,局部变量,局部对象的地址、全局指针类型,全局变量,全局对象等都不能作为非类型模板形参。 非类型模板的形参只能是整型,指针和引用。但是double &,double *,对象的引用或指针是正确的。
类模板中的静态数据成员是每个实例化后的类对象共有的,其初始化格式为:
template <class Type>
int 类名<Type>::变量名 = 10;
以下是一个使用类模板实现链表的代码,仅供参考:
#include <string>
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
using std::string;
class CSet
{
public:
CSet* m_pNext;
int m_Data;
CSet()
{
m_pNext = NULL;
}
};
class CNode
{
public:
CNode* m_pNext;
int m_Data;
CNode()
{
m_pNext = NULL;
}
};
template <class Type>
class CList
{
public:
CList()
{
m_pHeader = NULL;
m_NodeSum = 0;
}
~ CList()
{
if(m_NodeSum > 0)
{
Type* pDelete = m_pHeader;
Type* pTmp = NULL;
for(int i = 0;i < m_NodeSum;i++)
{
pTmp = pDelete->m_pNext;
delete pDelete ;
pDelete = pTmp;
}
m_NodeSum = 0;
pDelete = NULL;
pTmp = NULL;
}
m_pHeader = NULL;
}
Type* MoveTrail()
{
Type* pTemp = m_pHeader;
for(int i = 1;i < m_NodeSum;i++)
{
pTemp = pTemp ->m_pNext;
}
return pTemp;
}
void PassList()
{
if(m_NodeSum > 0)
{
Type* pTemp = m_pHeader;
cout<<"m_Data = "<<pTemp->m_Data<<" ";
for(int i = 1;i < m_NodeSum;i++)
{
pTemp = pTemp ->m_pNext;
cout<<" "<<pTemp->m_Data<<" ";
}
cout<<endl;
}
}
void AddNode(Type* pNode)
{
if(0 == m_NodeSum)
{
m_pHeader = pNode;
}
else
{
Type* pTrail = MoveTrail();
pTrail->m_pNext = pNode;
pNode->m_pNext = NULL;
}
m_NodeSum++;
}
private:
Type* m_pHeader;
int m_NodeSum;
};
int main()
{
CList<CNode> list;
for(int i = 0;i < 5;i++)
{
CNode* pCNode = new CNode;
pCNode->m_Data = i;
list.AddNode(pCNode);
}
list.PassList();
CList<CSet> list2;
for(int i =100;i < 105;i++)
{
CSet* pCSet = new CSet;
pCSet->m_Data = i ;
list2.AddNode(pCSet);
}
list2.PassList();
cin.get();
cin.get();
return 0;
}