目录
一、模板
1.1 模板的定义
模板是一种参数化多态性的工具,可以为逻辑功能相同而类型不同的程序提供代码共享的机制。分为函数模板和类模板。
1.2 泛型模板
用一个标志来表示类型,不是实际的类型。独立于任何特定类型的编程,c++的一个部分。
1.3 模板的特点
1.可用来创建动态增长和减小的数据结构。
2.它是类型无关的,因此具有很高的可复用性。
3.它在编译时而不是运行时检查数据类型,保证了类型安全。
4.它是平台无关的,可移植性。
5.可用于基本数据类型。
二、函数模板
2.1 函数模板基本格式
template<class T1,class T2> //或者是 template<typename T>
返回值 函数名(参数)
{
}
template:声明创建模板。
<>:用尖括号,里面可以一个或者多个通用类型。
class:(也可以用typename)表明后面的T1是一个通用类型,或者叫虚拟类型。
T1/T2:通用类型或者虚拟类型,(理解成类型)可以在函数中直接当做普通类型使用。
2.2 函数模板调用
1.函数名 <实际类型1,实际类型2>(参数列表);
显式类型推导 fun<int>(1,2);
2.函数名(参数);
隐形类型推导 fun(1,2);
3.注意:显示类型推导参数和推导的类型必须一致。
如果有普通函数和模板函数,在调用模板函数时可以用显示调用,省略类型的方式
swap<>(1,2);
2.3 函数模板和普通函数的区别
1.普通函数只可以有一种数据类型相匹配。函数模板有多种类型。
2.隐式推导优先使用普通函数,只有普通函数不匹配才使用函数模板。
3.函数模板只有在调用时,才会构建函数,而普通函数是在编译时。
4.普通函数调用时可以发生自动类型转换,而函数模板不行。
2.4 函数模板重载
和普通函数的重载相似。也是同一个作用域内函数名相同参数列表不同。
1.参数顺序不同重载
template <class T1,class T2>void swap1(T2 a,T1 b)
template <class T1,class T2>void swap1(T1 a,T2 b)
2.参数个数不同重载
template <class T>void swap1(T a)
template <class T1,class T2>void swap1(T1 a,T2 b)
3.注意:在函数参数顺序不同的重载中,实例化的时候不可以是相同类型。
swap1<int ,int >(1,2)
2.5 函数模板特化
1.定义:为了解决函数模板的局限性,在定义函数模板时候,直接确定好T的类型。也就是特定的类型模板。
2.格式:
template<class T>
返回值 函数名(类名& 对象)
{
}
3.匹配:如果传入的是自定义类型,并且和特化版本匹配,会优先使用特化版本。
4.注意:如果特化后,类型确定才可以使用自定义类型中的成员变量和方法。
2.6 多文件实现函数模板
在定义函数或者类的时候,会有.h文件和cpp文件,定义和申明是分开的。那么编译的时候就会出现连接错误的原因,这是因为函数模板是在调用时确定的,而调用时.h文件中没有函数实现,出现连接错误,找不到函数体。
解决方法:
1.在main中引用#include <xxx.h> 和 #include <xx.cpp>
2.将模板的定义和申明都放在.h头文件中。
2.7 函数模板的嵌套
1.定义:在函数模板中调用另外一个函数模板。
2.例如:
template<class T>
T max_2(T a,T b)
{
retirn a>b?a:b;
}
template<class T>
T max_3(T a,T b, Tc)
{
T temp=max_2(a,b);
return temp>c?temp:c;
}
2.8 函数模板的非类型参数
1. 定义:如果我们在使用函数模板时想给函数模板传入一个特定的确定参数,但又不希望放在小括号中。可以通过非类型参数实现。在模板<>中加了一个参数,但这个参数不是类型参数,是具体的某一个值。
2.格式:
template<class T,基本数据类型 变量名>
返回值 函数名(T& 变量)
{
}
3.例如:
template <class T,int size>
void showArr(T* arr)
{
}
在上述例子中,size是通过模板传入到函数中,可以当做普通变量使用。并且非类型参数都是常量,在函数中不允许修改,只可以使用,所以定义非类型参数变量时候,需要加const修饰。
三、类模板
3.1 类模板格式
1.格式:
template<typename T>
class person
{
T age;
};
2.实例化:
类名<类型> 变量名(参数);
person<int>zhangsn(18);
3.2 类模板和函数模板区别
1.函数模板可以使用隐式类型推导,但类模板不可以,必须显示推导。
2.类模板在定义template时候,可以加上默认参数。例如:
template<class T1,class T2=string>
3. 在模板中的默认参数类型中,如果所有模板参数都是缺省,但类模板进行实例化的时候,尖括号不可以省略。例如:
template<class T1=int,class T2=string>
class person
{
T1 age;
T2 name;
};
int main()
{
person<> wang(3,"wang");
return 0;
}