我们想要定义多个函数,每个函数比较一种给定类型的值,可能定义多个重载函数。
多个重载函数这两个函数几乎是相同的,唯一不同就是参数类型,函数体完全一样。可见是多么的烦琐,而且事先要确定可能要add的所有类型。
1.函数模板
我们可以定义一个通用的函数模板(function template),而不是为每个类型定义一个函数。函数模板就是一个公式,可以生成针对特定类型的函数版本。
函数模板模板定义以关键字template开始,后跟一个模板参数列表,这是一个逗号分隔的一个或多个模板参数的列表,用尖括号包围起来。在add中,用名字T表示一个类型,而T表示的实际类型则在编译时根据add的使用情况来决定。
1.1 模板类型参数
上述add函数只有一个模板类型参数。可以将类型参数看作类型说明符,就想内置类型或类型说明符一样使用,类型参数可以用来指定返回类型或函数的参数类型,以及在函数体内用于变量声明或类型转换。
模板参数列表类型参数前必须使用关键字class或typename,这个两个关键字含义相同,可以互相使用,但是typename比较直观。
1.2 非类型模板参数
非类型参数表示一个值而非一个类型,通过一个特定的类型名而非关键字class或typename。它被编译器推断出的值所代替,这些值必须是常量表达式。
非类型模板参数通过非类型模板就无需先知道数组p1的长度,一个非类型参数可以是一个整型,或者一个指向对象或者函数类型的指针引用。绑定到非类型模板参数的实参必须是个常量表达式,绑定到指针或引用非类型参数的实参必须具有静态的生存期。
2.类模板
类模板(class template)是用来生成类的蓝图的。与函数模板不同之处是,编译器不能为类模板推断模板参数类型,我们必须在模板名后的尖括号提供模板参数类型(i.e.vector<string>)。
2.1 定义类模板
类似函数模板,类模板以关键字template开始,后跟模板参数列表。在类模板及其成员的定义中,将模板参数当作替身,代替使用模板时用户需要提供的类型或值。定义一个类模板Blob如下:
类模板定义Blob模板有一个名为T的模板类型参数,用来表示Blob保存的元素类型,例如,将元素访问操作的返回类型定义T&。当用户实例化Blob时,T就会被替换为特定的模板实参类型。
2.2 实例化类模板
当使用类模板时,必须提供显示模板实参列表,编译器使用这些模板实参来实例化出特定的类。例如,为了用Blob模板定义一个类型,必须提供元素类型:
Blob<int> ia; //空Blob<int>
Blob<int> ia1 = {0,1,2,3,4}; // 有5个元素的Blob<int>
当编译器从Blob模板实例化出一个类时,会重写Blob模板,将模板参数T的每个实例替换为给定的模板实参,本例是int。
2.3 类模板的成员函数
既可以在类模板内部,也可以在类模板外部定义成员函数,且定义在类模板内的成员函数被隐式声明为内联函数。类模板的每个实例都有自己版本的成员函数,定义在类模板外的成员函数必须以关键字template开始,后接类模板参数列表。
check成员函数
网友评论