模板就是建立通用的模具,大大提高复用性
模板的特点:
-
模板不可以直接使用,它只是一个框架
-
模板的通用并不是万能的
-
C++另一种编程思想称为 ==泛型编程== ,主要利用的技术就是模板
-
C++提供两种模板机制:函数模板和类模板
函数模板
函数模板作用:
建立一个通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表。
语法:
template<typename T>
函数声明或定义
解释:
template --- 声明创建模板
typename --- 表面其后面的符号是一种数据类型,可以用class代替
T --- 通用的数据类型,名称可以替换,通常为大写字母
创建函数模板
//例子
template<typename T>
void mySwap(T& a, T& b)
{
T temp;
temp = a;
a = b;
b = temp;
}
调用函数模板
1 自动推导类型
直接正常调用,编译器会自己赋值
#include<iostream>
using namespace std;
template<typename T>
void mySwap(T& a, T& b)
{
T temp;
temp = a;
a = b;
b = temp;
}
int main()
{
int a = 1;
int b = 2;
mySwap(a, b);
printf("a=%d\n", a);
printf("b=%d\n", b);
return 0;
}
2 显示指定类型
通过尖括号直接模板的数据类型
#include<iostream>
using namespace std;
template<typename T>
void mySwap(T& a, T& b)
{
T temp;
temp = a;
a = b;
b = temp;
}
int main()
{
int a = 1;
int b = 2;
mySwap<int>(a, b);
printf("a=%d\n", a);
printf("b=%d\n", b);
return 0;
}
函数模板注意事项
1 自动类型推导必须推导出一致的数据类型
2 模板必须要确定出T的数据类型
函数模板总结
模板利用关键字template
使用函数模板有两种方式,自动类型推导和显示类型推导
模板提高复用性
函数模板案例
利用函数模板封装一个排序的函数,可以对不同类型数据进行排序
排序规则:从大到小,排序算法为选择排序
#include<iostream>
#include<string>
using namespace std;
template<typename T>
void mySort(T a[],int len)
{
for (int i = 0; i < len-1; i++)
{
for (int j = i + 1; j < len; j++)
{
if (a[j] > a[i])
{
T temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
}
void test()
{
char test[] = "Sna1lGo";
mySort(test, strlen(test));
printf("%s\n", test);
}
int main()
{
test();
return 0;
}
普通函数和函数模板的区别
1 普通函数调用时可以发生自动类型转换
2 函数模板调用时,如果利用自己类推导不会发生隐式类型推导
3 如果利用显示指定类型的方式,可以发生隐式类型推导
普通函数与函数模板的调用规则
1 如果普通函数和函数模板都可以调用,普通函数先调用
2 可以通过空模板参数列表来强制调用函数模板
3 函数模板也可以发生重载
4 如果函数模板可以产生更好的匹配,游戏调用函数模板
添加模板中的特殊情况
普通情况肯定没问题,但是如果要传入的是自己写的类,而又没有重载运算符,就可以写一个特殊情况的函数
template<> void compare(xxx a,xxx b)
{
}
类模板
类模板和函数模板是一样的,只是template中的参数必须为class,然后再在template下面写类就好了
这里的T也就是参数,可以随意添加
template<class T>
类
解释:
template --- 声明创建模板
typename --- 表面其后面的符号是一种数据类型,可以用class代替
T --- 通用的数据类型,名称可以替换,通常为大写字母
#include<iostream>
#include<string>
using namespace std;
template<class Nametype,class AgeType>
class role
{
public:
role(Nametype TEST_NAME, AgeType TEST_AGE) :test_name(TEST_NAME), test_age(TEST_AGE) {}
void show() {
cout << test_name << test_age << endl;
}
public:
Nametype test_name;
AgeType test_age;
};
void test()
{
role<string,int>p1("hello", 100);
p1.show();
}
int main()
{
test();
return 0;
}