跳到主要内容

C++ 模板

模板是 C++ 支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型。

  • 模板是一种对类型进行参数化的工具;
  • 通常有两种形式:函数模板和类模板;
  • 函数模板针对仅参数类型不同的函数;
  • 类模板针对仅数据成员和成员函数类型不同的类。

使用模板的目的就是能够让程序员编写与类型无关的代码。

注意:模板的声明或定义只能在全局,命名空间或类范围内进行。即不能在局部范围,函数内进行,比如不能在 main() 函数中声明或定义一个模板。

函数模板

定义模板函数的语法格式如下:

template <class type> ret-type func-name(parameter list)
{
// 函数的主体
}

其中,type 是函数所使用的数据类型的占位符名称。这个名称可以在函数定义中使用。

示例:定义一个函数模板,返回两个数种的最大值

#include <iostream>
#include <string>

using namespace std;

template <typename T>
inline T const& Max (T const& a, T const& b)
{
return a < b ? b : a;
}

int main(void)
{
int i = 39;
int j = 67;
cout << "Max(i, j): " << Max(i, j) << endl;

double f1 = 3.15;
double f2 = 20.87;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;

string s1 = "Hello";
string s2 = "GetIoT";
cout << "Max(s1, s2): " << Max(s1, s2) << endl;

return 0;
}

执行 g++ main.cpp && ./a.out 编译运行以上示例,输出结果如下:

Max(i, j): 67
Max(f1, f2): 20.87
Max(s1, s2): Hello

类模板

不仅可以定义函数模板,C++ 还允许定义类模板。类模板又称泛型类(Generic class)。

泛型类声明的一般语法格式如下:

template <class type> class class-name {
// ...
}

其中,type 是占位符类型名称,可以在类被范例化的时候进行指定。可以使用一个逗号分隔的列表来定义多个泛型数据类型。

示例:定义一个类 Stack<>,并实现了泛型方法来对元素进行入栈出栈操作

#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept>

using namespace std;

template <class T>
class Stack {
private:
vector<T> elems; // 向量,用来保存元素

public:
void push(T const&); // 入栈
void pop(); // 出栈
T top() const; // 返回栈顶元素
bool empty() const{ // 如果为空则返回真
return elems.empty();
}
};

template <class T>
void Stack<T>::push (T const& elem)
{
// 追加传入元素的副本
elems.push_back(elem);
}

template <class T>
void Stack<T>::pop ()
{
if (elems.empty()) {
throw out_of_range("Stack<>::pop(): empty stack");
}
// 删除最后一个元素
elems.pop_back();
}

template <class T>
T Stack<T>::top () const
{
if (elems.empty()) {
throw out_of_range("Stack<>::top(): empty stack");
}
// 返回最后一个元素的副本
return elems.back();
}

int main()
{
try {
Stack<int> intStack; // int 类型的栈
Stack<string> stringStack; // string 类型的栈

// 操作 int 类型的栈
intStack.push(17);
cout << intStack.top() <<endl;

// 操作 string 类型的栈
stringStack.push("Hello GetIoT");
cout << stringStack.top() << std::endl;
stringStack.pop();
stringStack.pop();
}
catch (exception const& ex) {
cerr << "Exception: " << ex.what() <<endl;
return -1;
}
}

编译运行以上程序,输出结果如下:

17
Hello GetIoT
Exception: Stack<>::pop(): empty stack