函数模板
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); // 不是友元
|
类模板与静态成员
类模板中可以定义静态成员,那么从该类模板实例化得到的每个模板类,都有自己的类模
板静态数据成员,该模板类的所有对象,共享一个静态数据成员