OOP09:Template
第9章 Template
相当于定义了一个 函数/类 的集合
9.1 函数模板
9.1.1 函数模板的声明
对不同的类型,执行相同的操作时,使用函数模板,比如swap、sort
| template <class T> // 或者是<typename T> | 
- template:声明模板
- class
T:声明了参数化类型的名字,在模板函数中,用T作为一个类型名
- 作为函数的参数
- 作为函数的返回值
- 作为函数的中间变量
 
9.1.2 函数模板的实例化 template instantiation
- 将一个真实的类型,带入template中
- 编译器会生成一个新的 函数/类 的定义
- 在生成的过程中,会检查 语法错误/不安全的调用
 
- 模板特化specialization
- 对特定的类型,执行新的模板函数
 
| int i = 3; int j = 4; | 
9.1.3 函数模板的使用要求
- 只有精确匹配,才能调用,不能执行类型转换 - swap(int, int); // ok 
 swap(double, double); // ok
 swap(int, double); // error!
- 函数模板、正常函数的命名可以是相同的,编译器会决定调用哪一个函数 - 首先,检查与正常函数的参数类型是否完全匹配
- 然后,检查是否与模板的参数相同
- 最后,进行类型转换
 - void f(float i, float k) { 
 cout << "f(float, float);\n";
 };
 template <class T>
 void f(T t, T u) {
 cout << "f(T, T);\n";
 };
 f(1.0, 2.0);//编译器默认浮点数为double, 此处编译器先判断为f(double, double), 符合模板的定义, 输出f(T,T);
 f(1, 2); //此处编译器先判断为f(int, int), 符合模板的定义, 输出f(T,T)
 f(1, 2.0); //此处编译器先判断为f(int, double), 不符合模板的定义, 进行类型转换, 1=>1.0f,2.0=>2.0f, 然后输出f(float, float);
- 编译器会推导T的实际类型,也可以自己手动定义 - 如果函数模板没有参数,则需要手动填写参数类型
- 参数可以有无限多个
 - template <class T> 
 void foo(void) { /* … */ }
 foo<int>(); // type T is int
 foo<float>(); // type T is float
9.2 类模板
由类型参数化parameterized的类
9.2.1 声明
| template <class T> | 
9.2.2 使用
必须手动填写类型
| Vector<int> v1(100); | 
9.2.3 定义成员函数
| template <class T> | 
9.2.4 类型参数的传递
| template <class T> | 
9.3 templates
- templates可以有多个参数 - template <class Key, class Value> 
 class HashTable{
 const Value& lookup (const Key&) const;
 void install (const Key&, const Value&);
 …
 }
- 参数的嵌套 - Vector< vector<double*> > //note space > > 
- 参数可以很复杂 - Vector< int (*) (Vector<double>&, int)> 
- 参数可以是具体的类型--非类型参数 non-type parameters - 每给一个bounds的值,编译器就会生成对应的代码,可能会导致编译出的代码过长
 - //声明 
 template <class T, int bounds = 100>
 class FixedVector{
 public:
 FixedVector();
 T& operator[](int);
 private:
 T elements[bounds]; // fixed size array!
 }
 //定义
 template <class T, int bounds>
 T& FixedVector<T, bounds>::operator[] (int i){
 return elements[i]; //no error checking
 }
 //调用
 FixedVector<int, 50> v1;
 FixedVector<int, 10*5> v2;
 FixedVector<int> v2; // 使用缺省值
9.4 模板与继承
- 模板类 可以继承于 非模板类 - template <class A> 
 class Derived : public Base{…}
- 模板类 可以继承于 模板类 - 基类的模板参数,从 派生类 中获得
 - template <class A> 
 class Derived : public List<A>{…}
- 非模板类 可以继承于 模板类 - 基类的模板参数,需要用户显式指定
 - class SupervisorGroup:public List<Employee*>{…} 
例:模拟virtual函数的调用(不借用虚函数表)
| template <class T> | 
9.5 注意
- 要把模板的定义和实现都放到头文件中
- 编译器会自动去除模板的重复定义
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 华风夏韵!
 评论
