1.函数模板
在构造函数的时候,我们常常会考虑传入的参数的数据类型,比如我们写一个大小比较的函数mycmp(class1 a,class1 b),则可以写出class1为int,float,double,string等各个种类的mycmp函数,这样会很麻烦,且当我们不知道传入参数类型的时候,甚至需要将他们都进行重载,才能完全实现大小比较函数的功能。这时,我们可以用一个函数模板多快好省地定义一批相似的函数,大大减少代码量。
函数模板定义格式:
Template<class 类型参数1,class 类型参数2.....>
返回值类型 模板名/函数名 (形参表){....(函数体)}
例如:
①函数模板中可以不止有一个类型参数
②可以不通过参数实例化函数模板
③函数模板可以重载,只要他们的形参表或者类型参数表不同
在有多个函数和函数模板名字相同的情况下,编译器如下处理一条函数调用语句:
先找参数完全匹配的普通函数(非由模板实例化而得的函数)。
再找参数完全匹配的模板函数。(在匹配模板函数时不能进行类型自动转换)
最后找实参数经过自动类型转换后能够匹配的普通函数。
上面的都找不到,则报错。
(*)函数模板的类型参数可以对应函数
2.类模板
与函数模板相似,为了多快好省地定义出一批相似的类,我们可以定义类模板,然后由类模板生成不同的类。
类模板:在定义类的时候,加上一个/多个类型参数。在使用类模板时,指定类型参数应该如何替换成具体类型,编译器据此生成相应的模板类。
类模板定义格式:
template<class 类型参数1,class 类型参数2.....>
class 类模板名 {....(成员函数和成员变量)}
在类体外书写成员函数时:
template<class 类型参数1,class 类型参数2.....>
返回值类型 类模板名<类型参数名列表>::成员函数名 (参数表){...(成员函数体)}
类模板定义对象时:
template <typename 类型参数 1, typename 类型参数 2, ……> //类型参数表
类模板名 < 真实类型参数表 > 对象名 (构造函数实参表);
编译器由类模板生成类的过程叫类模板的实例化。由类模板实例化得到的类,叫模板类。
注意:
(1)由同一个类模板实例化生成的两个模板类是不兼容的,即无法用其中一个模板类的指针指向另一个模板类的对象
(2)可以在类模板中书写函数模板作为成员函数
1.类模板的类型参数表中可以出现非类型参数
2.类模板同样可以进行派生和继承操作
①类模板从类模板派生
②类模板从模板类派生
③类模板从普通类派生
④普通类从模板类派生
3.类模板与友元
①函数、类、类的成员函数作为类模板的友元
②函数模板作为类模板的友元
③函数模板作为类的友元
注意:所有从
template <class T>
void Print(const T & p)
生成的函数,都成为 A 的友元。
但是自己写的函数 void Print(int a) { } 不会成为 A 的友元
④类模板作为类模板的友元
4.类模板与静态成员变量
类模板中可以定义静态成员,那么从该类模板实例化得到的每个模板类(由传入的参数类型决定),都有自己的类模板静态数据成员,该模板类的所有对象,共享一个静态数据成员。