C++ 笔记 | 第6课 模版
把类型参数化的程序被称为一个模板(template),使用模板只是简化程序的代码书写,并不能提高程序的执行效率。
C++ 模板主要针对函数和类等,形成: 函数模板、类模板、数组类模板
语法形式为: template < 模板参数表 > 声明
函数模版
编译系统会根据实际调用情况,由函数模板生成重载的模板函数实例。
如果一个函数模板声明定义中有局部的静态对象,那么这个静态对象也会在每个模板函数中被定义,各模板函数中的静态变量是相互独立的。
模版参数表可以是:class 标识符
和 typename 标识符
,标志符可以是数据类型或是类类型
C++ |
---|
1
2
3
4
5
6
7
8
9
10
11
12 | 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++ |
---|
| 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++ |
---|
| 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++ |
---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 | 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];
}
|