简介
C++中的模板和Java中的泛型一样,是支持参数化多态的工具。
通常有两种形式:函数模板和类模板
函数模板
template <class/typename 形参名,class/typename 形参名,......> 返回类型 函数名(参数列表)
{
函数体
}
例:
#include <iostream>
#include <string>
using namespace std;
template <typename T>
void swap_num(T &a, T &b)
{
T temp;
temp = a;
a = b;
b = temp;
}
int main()
{
int i = 10;
int j = 20;
cout << "i: " << i << ", j: " << j << endl;
swap_num(i, j);
cout << "i: " << i << ", j: " << j << endl;
string a = "a";
string b = "b";
cout << "a: " << a << ", b: " << b << endl;
swap_num(a, b);
cout << "a: " << a << ", b: " << b << endl;
return 0;
}
//输出
i: 10, j: 20
i: 20, j: 10
a: a, b: b
a: b, b: a
可以看到,函数swap_num有更好的通用性,而不用针对不同类型而定义多个swap_num函数。
类模板
类模板的格式为:
template<class/typename 形参名,class/typename 形参名,…> class 类名
{ ... };
例:
#include <iostream>
#include <string>
using namespace std;
template <class T, class V>
class Map
{
public:
T key; //关键字
V value; //值
Map(T k, V v)
{
key = k;
value = v;
};
};
int main()
{
Map<int, string> mymap1(1, "A");
Map<int, string> mymap2(2, "B");
cout << mymap1.key << "->" << mymap1.value << endl;
cout << mymap2.key << "->" << mymap2.value << endl;
return 0;
}
和Java中的定义泛型类还是很相似的。
注意: 模板的声明或定义只能在全局,命名空间或类范围内进行。即不能在局部范围,函数内进行,比如不能在main函数中声明或定义一个模板。
不过相比Java,C++模板特别的,有非类型形参的概念。
上例中的class T, class V,这种是叫类型形参,使用时需要传一个类型过去,如Map<int, string>中的int、string。
而非类型形参, 如template<class T, int a> class B{}; 其中int a就是非类型的模板形参。
下面写一个通用类型的栈:
#include <iostream>
#include <string>
using namespace std;
template <class T, int MAXSIZE>
class Stack
{ // MAXSIZE由用户创建对象时自行设置
private:
T elems[MAXSIZE]; // 包含元素的数组
int numElems; // 元素的当前总个数
public:
Stack(); //构造函数
void push(T const &); //压入元素
void pop(); //弹出元素
T top() const; //返回栈顶元素
bool empty() const
{ // 返回栈是否为空
return numElems == 0;
}
bool full() const
{ // 返回栈是否已满
return numElems == MAXSIZE;
}
};
template <class T, int MAXSIZE>
Stack<T, MAXSIZE>::Stack() : numElems(0) // 初始时栈不含元素
{
}
template <class T, int MAXSIZE>
void Stack<T, MAXSIZE>::push(T const &elem)
{
if (numElems == MAXSIZE)
{
throw out_of_range("Stack<>::push(): stack is full");
}
elems[numElems] = elem; // 附加元素
++numElems; // 增加元素的个数
}
template <class T, int MAXSIZE>
void Stack<T, MAXSIZE>::pop()
{
if (numElems <= 0)
{
throw out_of_range("Stack<>::pop(): empty stack");
}
--numElems; // 减少元素的个数
}
template <class T,int MAXSIZE>
T Stack<T,MAXSIZE>::top()const{
if (numElems <= 0) {
throw out_of_range("Stack<>::top(): empty stack");
}
return elems[numElems-1]; // 返回最后一个元素
}
int main()
{
try
{
Stack<int, 20> int20Stack; // 可以存储20个int元素的栈
int20Stack.push(7);
cout << int20Stack.top() << endl; // 7
int20Stack.pop();
int20Stack.pop();
}
catch (exception const &ex)
{
cerr << "Exception: " << ex.what() << endl;
return EXIT_FAILURE;
}
}
//输出
7
Exception: Stack<>::pop(): empty stack
其中int MAXSIZE就是非类型形参,在使用模板类的时候传入,在模板内部是常量值。
注:非类型形参只能是整型,指针和引用