跳转至

C++ 笔记 | 第6课 模版

把类型参数化的程序被称为一个模板(template),使用模板只是简化程序的代码书写,并不能提高程序的执行效率。

C++ 模板主要针对函数和类等,形成: 函数模板、类模板、数组类模板

语法形式为: template < 模板参数表 > 声明

函数模版

编译系统会根据实际调用情况,由函数模板生成重载的模板函数实例。

如果一个函数模板声明定义中有局部的静态对象,那么这个静态对象也会在每个模板函数中被定义,各模板函数中的静态变量是相互独立的。

模版参数表可以是:class 标识符typename 标识符,标志符可以是数据类型或是类类型

C++
template <模版参数表>
函数返回类型 函数模板名(形参表) {函数体}

// 如
template <typename T>
T abs(T a) {return a < 0 ? -a : a;}

// 如
template <class X, class Y>
X fun(X x, Y y) {  // 模板参数必须出现在函数声明的形参表中
  return x + y;
}

函数模版实参

在调用函数模板时,单独用函数模板实参来说明模板参数的类型

C++
1
2
3
4
template <class X, class Y, class Z>
Z fun(X x, Y y) {return x + y;}
// 调用
fun<int, long, double>(a, b)  // 给 X Y Z 直接赋值

在函数模板中,可以用一般修饰符说明的常规参数,

C++
1
2
3
4
5
6
7
8
9
template <typename T, int Rows, int Cols>
void sumRow(T data[][Cols], T result[]) {
  int i, j;
  for (i = 0; i < Rows; i++) {result[i] = 0;
    for (j = 0; j < Cols; j++) result[i] += data[i][j];
  }
}
// 调用
sumRow<double, 3, 4>(A, result);

冒泡排序模版

C++
using namespace std;
template <class ET>  // 也可写为 template <typename ET>

void bubsort(ET p[], int n) {
  int m, k, j, i;
  ET d;            // 用来交换的中间变量 k=0; m=n-1;
  while (k < m) {  // 子表未空
    j = m - 1;
    m = 0;
    for (i = k; i <= j; i++)  // 从前往后扫描子表
      if (p[i] > p[i + 1]) {  // 发现逆序进行交换
        d = p[i];
        p[i] = p[i + 1];
        p[i + 1] = d;
        m = i;
      }
    j = k + 1;
    k = 0;
    for (i = m; i >= j; i--)  // 从后往前扫描子表
      if (p[i - 1] > p[i]) {  // 发现逆序进行交换
        d = p[i];
        p[i] = p[i - 1];
        p[i - 1] = d;
        k = i;
      }
  }
  return;
}

类模版

C++
template <模板参数表> 
class 类名 {类成员声明}

成员函数若要在类模板外定义,需要写成下面的形式:

C++
template <模板参数表>
类型名 类名 <T>:: 成员函数名(形参表)

案例见CSDN | C++ 实例 | 栈类模版

类模版中的常量参数化

在类模板中,可以对常量进行参数化,这称为类模板的常量参数化。

C++
template <class T, int N>
class Array {
 public:
  T &operator[](int i);

 private:
  T buf[N];
};
template <class T, int N>  // 重载 [] 操作符函数模板
T &Array<T, N>::operator[](int i) {return buf[i];
}