- 模板概论
- 模板的分类
- 类属
- 函数模板
- 函数模板的使用
- 使用模板函数来实现选择排序
- 函数模板和函数模板
- 调用规则(主要体现在函数重载方面)
- 模板机制
- 模板的局限性
c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来代表。这个通用函数就成为函数模板。凡是函数体相同的函数都可以用这个模板代替,不必定义多个函数,只需在模板中定义一次即可。在调用函数时系统会根据实参的类型来取代模板中的虚拟类型,从而实现不同函数的功能。
用模板是为了实现泛型,可以减轻编程的工作量,增强函数的重用性
泛型编程主要利用的技术就是模板
模板分为 函数模板和类模板
模板的思想: 将类型参数化
- 函数模板
- 类模板
- 类型参数化,又称参数模板
实现类型的参数化
语法
//class = typename 随便用一个就可以 //这两行不能分开 template函数模板的使用void MySwap(T &a,T &b) { T temp = a; a = b; b = temp; } void test() { int a = 10; int b = 20; MySwap(a,b); //自动类型推导 double d1 = 3.14; double d2 = 2.14; MySwap (d1,d2); //显示指定类型 }
- 自动类型推导
- 显式指定类型
注意: 使用自动类型推导时必须推导出来一样的类型才能正确使用
模板不可以独立使用,必须要指定出T的类型才能调用
template函数模板和函数模板void MySwap(T &a,T &b) { T temp = a; a = b; b = temp; } template void PrintArray(T arr[], int len) { for (int i = 0; i < len; i++) { cout << arr[i] << endl; } } template void MySort(T arr[],int len) { for(int i = 0; i < len; ++i) { int max = i; for(int j = i+1; j < len; ++j) { if(arr[max] < arr[j]) { max =j; } } if(max != i) { MySwap(arr[max],arr[i]); } } } void test() { int arr[] = { 1,2,5,8,9,7,3,6,4 }; int len = sizeof(arr) / sizeof(arr[0]); MySort(arr, len); PrintArray(arr, len); }
区别: 普通函数可以发生隐式类型转换
函数模板使用自动类型推导时,不可以发生隐式类型转换
函数重载的条件:
- 同一作用域下 ,函数名称相同
- 参数类型不同
- 参数顺序不用
- 参数个数不用
调用规则
- 如果普通函数和函数模板都可以调用时,优先使用普通函数
- 如果想要强制调用函数模板,需要添加模板参数列表 <>
- 函数模板也可以发生函数重载]
- 如果函数模板可以产生更好的匹配,那么优先使用函数模板
模板实现机制
- 编译器并不是把函数模板处理成能够处理任何类型的函数(通过函数模板创建出来的函数为模板函数)
- 函数模板通过具体的类型产生不同的函数
- 编译器会对函数模板进行两次编译,在声明的地方对模板代码本身进行编译,在调用的地方对参数替换后的代码进行编译
模板并不是可以处理任意类型的,针对特殊的数据类型,可以通过具体化的代码来解决
Class Person
{
public:
int age;
string name;
}
template
bool MyCompare(T &a,T &b)
{
if(a == b)
{
return true;
]
return false;
}
//针对Person写的代码(也可以使用函数重载处理这种问题)
template<> bool MyCompare(Person &a,Person &b)
{
if(a.age == b.age && a.name == b.name)
{
return true;
}
return false;
}
void test()
{
Person p1("alufei",18);
Person p2("alufei",18);
bool ret = MyCompare(p1,p2);
}



