程序设计实习(6) —— 模板

函数模板

1
2
3
4
template <class T>
int foo(T a) {
    // 函数体
}

函数模板也可以有不止一个类型参数.

1
2
3
4
5
template <class T1, class T2>
T2 print(T1 arg1, T2 arg2) {
    cout << arg1 << " "<< arg2<<endl;
    return arg2;
}

也可以不通过参数实例化函数模板:

1
2
3
4
5
6
7
8
template <class T>
T Inc(T n) {
    return 1 + n;
}
int main() {
    cout << Inc<double>(4) / 2; // 输出 2.5
    return 0; 
}

函数模板可以重载,只要它们的形参表或类型参数表不同即可.

1
2
3
4
5
6
7
8
template<class T1, class T2>
void print(T1 arg1, T2 arg2);

template<class T>
void print(T arg1, T arg2);

template<class T,class T2>
void print(T arg1, T arg2);

注意: 匹配模板函数时不可以进行自动类型转换.

1
2
3
4
5
6
template<class T>
T myFunction(T arg1, T arg2);

myFunction(5, 7); // ok: replace T with int
myFunction(5.8, 8.4); // ok: replace T with double
myFunction(5, 8.4); // error, no matching function

类模板

在定义类的时候,加上一个/多个类型参数. 在使用类模板时, 指定类型参数应该 如何替换成具体类型,编译器据此生成相应的模板类.

1
2
3
4
template <class T>
class MyClass {
    T data;
}

编译器由类模板生成类的过程叫类模板的实例化. 由类模板实例化得到的类叫模板类. 同一个类模板的两个模板类是不兼容的.

1
2
3
pair<string, int> *p;
pair<string, double> a;
p = &a; // wrong

类型参数表可以出现非类型参数.

类模板与派生

  • 类模板从类模板派生
  • 类模板从模板类派生
  • 类模板从普通类派生
  • 普通类从模板类派生

类模板与友元

  • 函数、类、类的成员函数作为类模板的友元
  • 函数模板作为类模板的友元
  • 函数模板作为类的友元
  • 类模板作为类模板的友元 普通类从模板类派

需要注意, 如果手动实现函数的特化, 则不会成为友元.

1
2
3
4
5
6
7
8
9
class A {
    int v;
public:
    A(int n):v(n) { }
    template <class T> friend void Print(const T & p);
};

template <class T> void Print(const T & p);
void Print(int p); // 不是友元

类模板与静态成员

类模板中可以定义静态成员,那么从该类模板实例化得到的每个模板类,都有自己的类模 板静态数据成员,该模板类的所有对象,共享一个静态数据成员

本文遵循 CC BY-NC-SA 4.0 协议
使用 Hugo 构建