1. 为什么要定义模板
泛型思想,类型参数化
2. 模板的基础
2.1 模板的形式
模板参数列表中,可以有多个参数,并且参数是可以赋初值的
/* template <class T> */
template <typename T, typename T2 = double>
T add(T x, T2 y)
{
cout << "T add(T x, T2 y)" << endl;
return x + y;
}
2.2 实例化
显式实例化:显式的将烈性参数写出来,以免靠编译器去推导
隐式实例化:不主动写出参数类型,靠编译器自己推导
![]()
2.3 模板的特点
- 普通函数和函数模板是可以同时存在的
- 普通函数是优先于函数模板执行的
- 普通函数与函数模板之间可以形成重载
- 函数模板和函数模板之间也可以形成重载
2.4 模板的特化
模板的特化(将模板的参数以特殊值展示出来)
1. 全特化(将所有的模板参数都以特殊形式展示出来)
2. 部分特化(偏特化)(将模板的参数特化出一部分,至少有一个没有特化)
![]()
2.5 模板不能分成头文件与实现文件
2.6 模板参数类型
- 类型参数,比如T
- 非类型参数,都是整型(bool/int/short/char/size_t/long/long long/void *),排除了浮点型float/double
![]()
2.7 成员函数模板
成员函数也是可以使用模板形式
![]()
3. 可变模板参数
// 递归出口
void print()
{
cout << endl;
}
// ...位于Args左边称为打包
template <typename T, typename ...Args> // Args模板参数包
void print(T t, Args ...args) // args函数参数包
{
cout << t << " ";
print(args...); // ...位于args右边称为解包
// 获取可变参数参数个数 cout << sizeof...(Args) << endl;
}
函数模板可变参数解包过程
4. 类模板
例子:
#include <iostream>
using namespace std;
template <typename T = int, size_t kSize = 10>
class Stack
{
public:
Stack()
: _top(-1)
, _data(new int[kSize]())
{
cout << "Stack()" << endl;
}
~Stack()
{
cout << "~Stack()" << endl;
if (_data)
{
delete [] _data;
_data = nullptr;
}
}
bool empty();
bool full();
void push(T t);
void pop();
T top();
private:
int _top;
T *_data;
};
template <typename T, size_t kSize>
bool Stack<T, kSize>::empty()
{
return (-1 == _top);
}
template <typename T, size_t kSize>
bool Stack<T, kSize>::full()
{
return (_top == kSize - 1);
}
template <typename T, size_t kSize>
void Stack<T, kSize>::push(T t)
{
if (!full())
_data[++_top] = t;
else
{
cout << "The Stack is full." << endl;
return;
}
}
template <typename T, size_t kSize>
void Stack<T, kSize>::pop()
{
if (!empty())
--_top;
else
{
cout << "The Stack is empty." << endl;
return;
}
}
template <typename T, size_t kSize>
T Stack<T, kSize>::top()
{
return _data[_top];
}
void test()
{
Stack<int, 20> st;
cout << "栈空了吗?" << st.empty() << endl;
st.push(1);
cout << "栈满了吗?" << st.full() << endl;
for (size_t idx = 2; idx < 30; idx ++)
{
st.push(idx);
}
cout << "栈满了吗?" << st.full() << endl;
while(!st.empty())
{
cout << st.top() << " ";
st.pop();
}
cout << endl;
cout << "栈空了吗?" << st.empty() << endl;
}
int main(int argc, char **argv)
{
test();
return 0;
}
注意:成员函数模板不能声明为virtual