![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/497346a1ba143cbb6938750f5d797bf5.png)
1. 泛型编程
泛型编程是一种编程范式,它允许在编写代码时使用一种抽象的方式来处理数据类型。通过泛型编程,程序员可以编写通用的代码,而不需要关注具体的数据类型。这样可以提高代码的重用性和灵活性,同时减少重复编写类似的代码的工作量。
模板就是泛型编程的基础,它分为函数模板和类模板。
2. 函数模板
2.1 概念
函数模板是一种通用的函数定义,它可以用于创建多个具有相似功能但类型不同的函数,在使用时参数化,根据参数的类型产生版本不同的函数。
2.1 使用格式
template <class/typename 形参名,class/typename 形参名,......>
返回类型 函数名(参数列表)
{
函数体
}
说明:
- template是关键字,有模板的意思
- class、typename也是关键字,在模板函数中可以互换,只是有一些微小的区别:class关键字通常用于声明类类型参数,typename关键字通常用于声明任意类型参数。但是这里不能使用struct。
例子:
template<typename T>
void Swap(T& t1, T& t2)
{
T tmp = t1;
t1 = t2;
t2 = tmp;
}
int main()
{
int t1 = 3;
int t2 = 4;
Swap(t1, t2);
cout << "t1: " << t1 << endl << "t2: " << t2 << endl;
double t3 = 2.2;
double t4 = 3.3;
Swap(t3, t4);
cout << "t3: " << t3 << endl << "t4: " << t4 << endl;
return 0;
2.2 原理
模板函数只是一个模具,它本身不是函数,在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。
2.3 模板函数的实例化
模板函数的实例化是指根据模板函数的定义,再根据具体的数据类型或参数类型生成具体函数的过程。它分为显示实例化和隐式实例化。
- 隐式实例化:让编译器根据传入的参数自己推演出参数类型。
template <class T>
T add(T a, T b)
{
return a + b;
}
int main()
{
cout << add(1, 2) << endl;
return 0;
}
但如果出现下面这种情况
int main()
{
cout << add(1, 2.2) << endl;
return 0;
}
这里编译器会报错,因为编译器不知道将类型推断成int还是double,这里使用显示实例化是一种解决办法。
- 显示实例化:在函数名后的<>中指定模板参数的实际类型
template <class T>
T add(T a, T b)
{
return a + b;
}
int main()
{
cout << add<double>(1, 2.2) << endl;
return 0;
}
注:如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。
2.4 模板参数匹配原则
当一个普通函数和模板函数同名并且该模板函数可以实例化成该普通函数的情况。(相当于一个是现成的,还有一个只有图,后续需要制作)
template <class T>
T add(T a, T b)
{
cout << "T add(T a, T b)" << endl;
return a + b;
}
int add(int a, int b)
{
cout << "int add(int a, int b)" << endl;
return a + b;
}
现在在主函数传参,大家可以猜猜编译器是调用哪个函数。
int main()
{
add(1, 1);
add(1.0, 1);
add(1.0, 1.0);
return 0;
}
由此上面我们可以得出结论:
(1)如果参数刚好匹配,直接用现成的。
(2)勉强匹配,直接用现成的。
(3)有更匹配的,哪怕只有蓝图,也用那个。
3. 类模板
3.1 类模板的定义格式
template<class T1, class T2, ..., class Tn>
class T
{}
例子:
template <class T1,class T2>
class Student
{
public:
void Print()
{
cout << _name << endl;
cout << _age << endl;
}
private:
T1 _name;
T2 _age;
};
3.2 类模板的实例化
类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。
template <class T1,class T2>
class Student
{
public:
Student(T1 name, T2 age)
:_name(name)
,_age(age)
{}
void Print()
{
cout << _name << endl;
cout << _age << endl;
}
private:
T1 _name;
T2 _age;
};
int main()
{
Student<string, int> s("张三", 18);
s.Print();
}