模板的通用性并不是万能的
函数模板的局限性
- 函数模板通过具体类型产生不同的函数(模板的实现机制)
- 函数模板的通用性并不是万能的,如果给通用类型T(泛型思想)传入一个用户自定义数据类型,虽然看上去没有什么错误,但是编译时报错
#include<iostream>
using namespace std;
//模板的局限性
class Person {//用户自定义类型Person
public:
string m_Name;
int m_Age;
Person(string name, int age) {
this->m_Name = name; this->m_Age = age;
}
};
//myComepare()函数模板的定义,编译器会对函数模板进行两次编译,在定义的地方对模板代码本身进行编译,在调用的地方对参数替换后的代码进行编译。(模板的实现机制)
template<typename T>
bool myComepare(T& a, T& b) {//Compare v.比较,对比,形参是两个引用(别名/指针常量)
if (a == b)return true;
else return false;
}
void test() {
Person p1("小明", 18);
Person p2("小明", 18);
//myComepare()函数模板的调用,调用时对函数模板进行第二次编译,看上去没有语法错误,但是编译时报错
bool ret = myComepare(p1, p2);
if (ret) cout << "p1对象等于p2" << endl;
else cout << "p1对象不等于p2" << endl;
}
int main() {
test();
system("pause");
return 0;
}
编译器会对函数模板进行两次编译,在声明的地方对模板代码本身进行编译,在调用的地方对参数替换后的代码进行编译。(模板的实现机制)
给通用类型T传入用户自定义类型Person,虽然看上去没有语法错误,但是编译时报错。
编译该调用时,替换通用类型T为Person该函数内部进行两个对象是否相等比较,我并没有对 == 号运算符重载,显然不可进行比较。
利用具体化的模板解决函数模板的局限性
有两种方式解决函数模板无法进行两个自定义类型的比较,第一种是运算符重载,但是利用运算符重载的话,要重载多个比较运算符。(如operator==、>、<、>=、<=)
第二种方式,提供一个具体化的Person类型的模板(函数模板重载,具体化通用类型T的类型为Person),具体化的模板优先调用。
将以下代码和上方代码关联,可以解决函数模板自定义类型的通用化
//提供一个具体化的Person类型的模板(函数模板重载,具体化通用类型T的类型为Person)
template<> bool myComepare(Person &a, Person &b) { //加tenplate<>关键字,告诉编译器这是一个函数模板myComepare()的重载
if (a.m_Name==b.m_Name&&a.m_Age==b.m_Age)return true;
else return false;
}
/*总结:利用具体化的模板,可以解决函数模板自定义类型的通用化
* 学习模板并不是为了写模板,而是在STL能够运用系统提供的模板
*/
总结:学习模板并不是为了写模板,而是在STL能够运用系统提供的模板