模板

来源:互联网 发布:店侦探看店宝插件mac 编辑:程序博客网 时间:2024/04/28 15:48
 
一、模板的定义与使用
模板定义以template开头,后跟一对尖括号,尖括号内是模板形参列表,以逗号隔开,不能为空。形参的类型是classtypename,它们是等价的。
template<typename T1, class T2>
…….
1
、函数模板
一个典型的函数模板
template <typename T>
 
int compare (const T &v1, const T &v2)
 
{
       
if (v1<v2) return -1;
       
if (v2<v1) return 1;
       
return 0;
 }

在使用函数模板时可不用指定具体的类型,编译器会自动推导。以下两种调用方法是等价的。
compare(1,2);
compare<int>(1,2);
2、类模板
一个典型的类模板
template<typename T>
class stack
{
    
public:
           
void push (const T&);
           T pop();
           
bool empty();
 
    
private:
           vector
<T> m_vector;
}

 
类外定义成员函数的格式:
template <typename T>
ret_type stack
<T>::member-name
使用类模板则必须指定形参类型:
stack<int> myStack;
 
3、特别说明
Ø         模板声明和实现中的形参名称不必相同
Ø         模板形参的名字不可在模板内部重用
Ø         在模板内部指定类型时要使用typename关键字。
typename Param::size_type * p; // 区别指针和乘积
Ø         模板的形参可以是非类型的,但必须是常量表达式。
 
二、模板实例化
         产生具体类型的模板实例的过程叫做实例化。前面已经说过,类模板的实例化必须指定类型,函数则可不指定,编译器会代劳推导出来的。另外需要注意的是stack<int>stack<string>是完全不同的两种类型,他们之间没有任何的瓜葛,相互不具有特殊的访问权限。
1、   模板实参推断
Ø         多个模板类型形参的实参必须完全匹配
加入shshort类型,则compare(sh, 1024)是错误的调用,因为第一个参数匹配short,而第二个匹配int,导致推断错误。
Ø         模板类型形参的受限转换
模板实参只会进行两种转换:一是const转换,即形参为const指针或引用的函数接受非const的指针和引用的调用;一是数组或函数到指针的转换。
 
三、模板特化
         针对特殊类型作出特殊处理
1、   函数模板特化
template<>
function
<T> (…)
{

}

2、  
类模板特化
template<>
classname
<T>
{

}
;
 
在类外特化成员函数时不可使用
template<>。但在特化成员而不特化类时,又另当别论,好晕哦。
template<>
void stack<int>::push(const int &val)
{

}

 
3、   偏特化
只特化模板形参的一部分而非全部。
4、   重载与函数模板
如果重载函数中既有普通函数又有函数模板,确定函数调用的步骤如下(非模板函数优先):
Ø         为这个函数名建立候选函数集合,包括:同名的任意普通函数,同名的类型匹配的函数模板实例化
Ø         确定那些普通函数是可行的,模板实例都是可行的(因为是编译器推导出来的)
Ø         如果需要转换来进行调用,根据转换的种类排列可行函数。如果只有一个函数可选,则调用它;如果调用具有二义性,从可行函数集合中去掉所有函数模板实例
Ø         重新排列去掉函数模板实例的可行函数。如果只有一个函数可选,则调用;否则具有二义性。