由于C++是静态语言,在所有的变量声明时都必须加上它的类型。静态语言的好处是能够在编译期就能检查出类型错误,但同时也带来了一些不便。比如一个比较大小的函数:
int Max(int a,int b){ return a>b?a:b; }
但这个函数只能对int类型的数据生效,如果传入的参数是float或者是double类型的,都会报错。如果想比较浮点数据的大小,就得重新定义一个函数。这样使得代码变得非常臃肿。
好在C++提供了一个很好的解决方案——模板。
模板函数
模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。
模板是创建泛型类或函数的蓝图或公式。库容器,比如迭代器和算法,都是泛型编程的例子,它们都使用了模板的概念。
定义模板函数的语法为:
template <typename type> return-type function-name(parameter list) { // 函数的主体 }
其中:type是函数所使用的数据类型的占位符名称。这个名称可以在函数定义中使用。但一般使用大写字母T。它仅仅是一个占位符,会根据传入的参数类型来自动适配。但需要注意的是,一个占位符在一次调用中仅能转换成一种类型。例如:
#include<iostream> using namespace std; template<typename T> T Max(T a, T b) { return a > b ? a : b; } int main() { int a = 1, b = 2; cout << Max(a, b) << endl; float c = 1.1, d = 2.2; cout << Max(c, d) << endl; char e = 'a', f = 'z'; cout << Max(e, f) << endl;
//如果传入的参数是a和c,就会报错
//cout<<Max(a,c)<<endl;
}
如果想适配两个不同类型的数据,就需要定义两个不同的占位符:
#include<iostream> using namespace std; template<typename T,typename F> T Max(T a, F b) { return a > b ? a : b; } int main() { int a = 1; float b = 2.1; cout<<Max(a,b)<<endl; }
最终输出的结果为2,而不是2.1。因为在比较整数与浮点数的时候,C++会自动的把浮点数转换为整数,故最后返回的结果为2。
类模板
与函数模板一样,我们也可以定义类模板。泛型类声明的一般形式如下所示:
template <class type> class class-name { . . . }
与函数模板不同的是,类模板中的占位符不是根据传入的参数自动适配的,而是在实例化的时候需要将实际的类型作为模板参数传入,从而来指定占位符实际代表的类型:
#include<iostream> using namespace std; template<class T> class Box { public: T height; }; int main() { Box<int> box1; box1.height = 10; Box<float> box2; box2.height = 9.8; cout << box1.height << "\n" << box2.height << endl; }
当然,也可以像函数模板一样,使用一个逗号分隔的列表来定义多个泛型数据类型。