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 许可协议。转载请注明来自 华风夏韵!
评论