模板是泛型编程的一种,所谓泛型编程就是编写与类型无关的逻辑代码,是一种复用方式,模板分为模板类和模板函数
下面是普通的函数调用
#include<iostream>
using namespace std;
bool IsEqual(int left, int right)
{
return left == right;
}
bool IsEqual(const string& left, const string& right)
{
return left == right;
}
void test1()
{
string s1("s1");
string s2("s2");
cout << IsEqual(s1, s2) << endl;
cout << IsEqual(1, 1) << endl;
}
int main()
{
test1();
system("pause");
return 0;
}
可以发现上面的代码虽然可以正确的运行,但是有缺点,比如当需要比较其它类型的数据时,就需要再写对应类型的函数。这样不仅浪费时间,还是代码变得更加冗余,调试不方便。C++中解决这个问题,可以采用模板。
函数模板的格式:
template
template<typename T>
bool IsEqual(const T& left, const T& right)
{
return left == right;
}
void test()
{
string s1("s1");
string s2("s2");
cout << IsEqual(s1, s2) << endl;
cout << IsEqual(1, 1) << endl;
}
int main()
{
test();
system("pause");
return 0;
}
下面是程序执行时的反汇编代码,进一步验证了上图中模板函数的实例化
cout << IsEqual(s1, s2) << endl;
001B8790 rcl byte ptr [edx-75h],1
001B8793 or eax,1C0090h
001B8798 call dword ptr ds:[1C009Ch]
001B879E cmp edi,esp
001B87A0 call __RTC_CheckEsp (01B130Ch)
001B87A5 mov ecx,eax
001B87A7 call dword ptr ds:[1C00A0h]
001B87AD cmp esi,esp
001B87AF call __RTC_CheckEsp (01B130Ch)
cout << IsEqual(1, 1) << endl;
001B87B4 mov dword ptr [ebp-12Ch],1
001B87BE mov dword ptr [ebp-120h],1
001B87C8 mov esi,esp
001B87CA push 1B1497h
001B87CF lea eax,[ebp-12Ch]
001B87D5 push eax
001B87D6 lea ecx,[ebp-120h]
001B87DC push ecx
001B87DD call IsEqual<int> (01B1488h)
001B87E2 add esp,8
001B87E5 mov edi,esp
001B87E7 movzx edx,al
001B87EA push edx
001B87EB mov ecx,dword ptr ds:[1C0090h]
001B87F1 call dword ptr ds:[1C009Ch]
001B87F7 cmp edi,esp
001B87F9 call __RTC_CheckEsp (01B130Ch)
001B87FE mov ecx,eax
001B8800 call dword ptr ds:[1C00A0h]
001B8806 cmp esi,esp
001B8808 call __RTC_CheckEsp (01B130Ch)
模板函数也可以看作重载函数,但是是有条件的,比如如果像上面的图一样将IsEqual函数屏蔽掉,那么模板函数不是重载函数,因为它没有实例化,只有实例化后,它才能视为重载函数,理由上面的图中已经说明了。
模板参数匹配及显示实例化
void test1()
{
cout << IsEqual(1, 1) << endl;//结果为1
//cout << IsEqual(1, 1.2) << endl;//模板参数不匹配,编译不通过
cout << IsEqual<int>(1, 1.2) << endl;//将两个参数全部实例化成int类型,结果为1
cout << IsEqual<double>(1, 1.2) << endl;//将两个参数全部实例化成double类型,结果为0
}
需要说明的是如果已经存在与某种类型有关的IsEqual函数,那么将直接调用这个IsEqual函数,不在进行实例化。//cout << IsEqual(1, 1.2) << endl;//这样调用编译会不通过,因为模板参数不匹配,编译器不知道到底要实例化成int类型还是double类型。cout << IsEqual(1, 1.2) << endl;这样调用是合法的,编译器不再进行推演,而是直接将两个参数全部实例化成int类型。
以上均是模板函数,关于类模板可以参考http://blog.csdn.net/nou_camp/article/details/69822642
http://blog.csdn.net/nou_camp/article/details/69844255
模板的优点:复用了代码, 节省了资源更快的迭代开发。C++的标准模板库(STL)因此而产生。增强了代码的灵活性。
模板的缺点:模板让代码变得凌乱复杂,不易维护,编译代码时间变长。搬移出错时,错误定位不准确。