什么是泛型编程?
泛型程序设计(generic programming)是程序设计语言的一种风格或范式。泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。
泛型编程大大提高了代码的复用性,从而也很大程度提高了开发的效率
C++中的泛型即被称为模板。
什么是模板?
模板语法:template<typename T>/template<class T>
ps:此处的template和typename同为关键字
tips:typename即会自动识别类型(typename与class在该处的语法功能上是完全相同的)
其二者还有唯一一个区别,typename还可用于声明嵌套依赖类型
即当一个模板类中出现了其它作用域的自定义对象成员时,该成员需要选择是否用typename来修饰,以区分是一个类型还是成员名称。如下:
class MyArray { public: typedef int LengthType; ..... } template<class T> void MyMethod( T myarr ) { typedef typename T::LengthType LengthType; LengthType length = myarr.GetLength; }
MyMethod方法中的T::LengthType有可能是某个作用域下的静态成员或者静态函数,也可能是某个类型,编译器无法知道到底是什么,所以此时typename的作用就是告诉 c++ 编译器,typename后面的字符串为一个类型名称,而不是成员函数或者成员变量
ps:由于模板的特殊性,其不支持分离编译(即声明在.h文件,实现在.cpp文件)
(理由其实也很好理解,分离编译时,.cpp文件内的方法定义都会分配地址,生成对应的符号表,但是模板只有在实例化时才会为其分配空间,也就是说如果只有模板没有实例化则不会为模板分配空间。这样即与分离编译产生了矛盾,故此不支持分离编译)
什么是模板函数?
模板函数语法:
template<typename T>
T add(T a, T b){
return a+b;
}
模板函数其实本质只是类似图纸,实际函数调用时会根据类型生成对应新的函数
并非直接调用该模板函数,而是编译器生成新的函数
模板函数传参时不能进行隐式类型转换,其在推导类型T时会产生矛盾
如下: 正常函数传参时是支参数进行隐式类型转换的,但模板则因为无法推导具体类型而不支持
使用模板函数应注意:
- 调用模板函数时,可以直接进行传参,进行隐式实例化模板
也可以通过函数名<类型>(参数)指定参数类型的方式进行显式实例化模板 - 当T(自定义类型)未出现在参数列表里,仅出现在函数体内时则必须显示实例化该模板函数
- 如果有同名正常函数与模板函数同时存在时,则是先优先匹配调用已有的同名函数
使用模板函数时,都会优先使用更合适的模板函数
什么是类模板?
使用方式上与模板函数基本相同,就不再多做介绍
需要注意类模板在使用时都需要显式实例化模板
template<typename T>
class Entity{
T entity;
};
类模板一般不建议声明与定义分离,如若要进行声明定义分离,可以考虑将类模板声明在头文件中
更多细节可以参见一下:Why can templates only be implemented in the header file?
The End.