模板
来源:互联网 发布:店侦探看店宝插件mac 编辑:程序博客网 时间:2024/04/28 15:48
一、模板的定义与使用
模板定义以template开头,后跟一对尖括号,尖括号内是模板形参列表,以逗号隔开,不能为空。形参的类型是class或typename,它们是等价的。
template<typename T1, class T2>
…….
…….
一个典型的函数模板
template <typename T>
int compare (const T &v1, const T &v2)
...{
if (v1<v2) return -1;
if (v2<v1) return 1;
return 0;
}
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;
}
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
ret_type stack<T>::member-name
3、特别说明
Ø 模板声明和实现中的形参名称不必相同
Ø 模板形参的名字不可在模板内部重用
Ø 在模板内部指定类型时要使用typename关键字。
typename Param::size_type * p; // 区别指针和乘积
Ø 模板的形参可以是非类型的,但必须是常量表达式。
二、模板实例化
产生具体类型的模板实例的过程叫做实例化。前面已经说过,类模板的实例化必须指定类型,函数则可不指定,编译器会代劳推导出来的。另外需要注意的是stack<int>和stack<string>是完全不同的两种类型,他们之间没有任何的瓜葛,相互不具有特殊的访问权限。
1、 模板实参推断
Ø 多个模板类型形参的实参必须完全匹配
加入sh是short类型,则compare(sh, 1024)是错误的调用,因为第一个参数匹配short,而第二个匹配int,导致推断错误。
Ø 模板类型形参的受限转换
模板实参只会进行两种转换:一是const转换,即形参为const指针或引用的函数接受非const的指针和引用的调用;一是数组或函数到指针的转换。
三、模板特化
针对特殊类型作出特殊处理
1、 函数模板特化
template<>
function<T> (…)
...{
…
}
function<T> (…)
...{
…
}
template<>
classname<T>
...{
…
};
classname<T>
...{
…
};
template<>
void stack<int>::push(const int &val)
...{
…
}
void stack<int>::push(const int &val)
...{
…
}
3、 偏特化
只特化模板形参的一部分而非全部。
4、 重载与函数模板
如果重载函数中既有普通函数又有函数模板,确定函数调用的步骤如下(非模板函数优先):
Ø 为这个函数名建立候选函数集合,包括:同名的任意普通函数,同名的类型匹配的函数模板实例化
Ø 确定那些普通函数是可行的,模板实例都是可行的(因为是编译器推导出来的)
Ø 如果需要转换来进行调用,根据转换的种类排列可行函数。如果只有一个函数可选,则调用它;如果调用具有二义性,从可行函数集合中去掉所有函数模板实例
Ø 重新排列去掉函数模板实例的可行函数。如果只有一个函数可选,则调用;否则具有二义性。