模板的介绍和使用
一.模板的基础概念
模板主要分为函数模板和类模板,其目的是类型参数化。简单来说就是在自己自定义的函数会存在不同数据类型,模板能适用于通用数据类型。


#include
#include
#include
#include
using namespace std;
template
T add(const T& left, const T& right) {
return left + right;
}
int main()
{
//类型自动为int
cout << add(1, 2) << endl;
//类型定义为char
cout << add
//类型定义为int
cout << add
return 0;
}
二.类模板的基础
在类和对象的基础上进行定义,我们来实现一个栈的操作为例:


template
class Stack {
public:
Stack(int capacity = 4)
:_array(new T[capacity])
,_top(0)
,_capacity(capacity){}
~Stack() {
delete[] _array;
_top = 0;
_capacity = 0;
}
//扩容
void push(const T& x) {
if (_top == _capacity) {
//2倍扩容
T* tmp = new T[_capacity * 2];
for (size_t i = 0; i < _top; i++) {
tmp[i] = _array[i];
}
delete[] _array;
_array = tmp;
_capacity *= 2;
}
_array[_top++] = x;
}
void Pop() {
assert(_top > 0);
_top--;
}
T& Top() {
assert(_top > 0);
return _array[--_top];
}
bool Empty() const {
return _top == 0;
}
private:
T* _array;
int _top;
int _capacity;
};
int main()
{
//int类型
Stack
intStack.push(1);
intStack.push(2);
cout << intStack.Top() << endl;
intStack.Pop();
cout << intStack.Top() << endl;
//double类型
Stack
a.push(3.14);
a.push(2.22);
cout << a.Top() << endl;
a.Pop();
cout << a.Top() << endl;
return 0;
}
其主要作用是一个函数可以接受多个数据类型的参数。
三.非模板类型
有一定的使用条件:
可以用于整数类型、枚举类型、引用指针一类。而不能用于浮点数字符串这些。


// 模板元编程:使用非类型模板参数进行编译期计算
template
struct Fibonacci {
// 编译期计算斐波那契数:F(N) = F(N-1) + F(N-2)
static const int value = Fibonacci
};
// 模板特化:递归终止条件
template <>
struct Fibonacci<0> {
static const int value = 0;
};
template <>
struct Fibonacci<1> {
static const int value = 1;
};
int main() {
// 编译期计算,运行时直接取值
cout << Fibonacci<10>::value << endl; // 输出:55
cout << Fibonacci<20>::value << endl; // 输出:6765
return 0;
}
四.模板的分离编译

我们的模板只有在使用时才会被实例化,而在其他的文件中只有声明,而没有声明。具体的流程如图:

为了解决这个问题,我们一般有两个方法:
1.将模板的声明和定义放在一个头文件中。
2.显式实例化模板。
而开发中我们一般都采用第一个方法,第二个方法费内存而且效率低。
五.模板的优缺点














