上次写了个Max函数,那么它能用来比较字符串吗?
我们传进 需要去的参数是地址,函数将直接比较两个地址的大小,所以显然不能比较字符串,那么如何让它能够比较字符串呢,我们就需要对模板函数进行特化
1 模板函数特化:有时候我们并不能够写出对所有可能被实例化的模型都合适的模板,有些时候通用模板也有可能处理不了某个特定的类型,这时就需要对模板函数进行特化
现在我们来看特化后的字符串比较函数
template <typename T>
int compare(const T &r, const T &l)
{
if (r > l)
{
return 1;
}
else if (r == l)
{
return 0;
}
else
return -1;
}
template<>
int compare<const char* &>(const char*&pl, const char* &pr)
{
return strcmp(pl, pr);
}
int main()
{
const char* p1 = "123";
const char* p2 = "456";
compare(p1, p2);
compare<const char* &>(p1, p2);
char* p3 = "222";
char* p4 = "123";
compare(p3, p4);
}
看起来是不是非常简单,但是需要注意的地方也不少
1)模板函数的定义形式如下:
关键字template后面跟一对空的< >
模板名<特化定义的模板形参>函数形参表
函数体
eg:template<>
int compare
eg:template< >
int compare<int>(int)
{
return 0;
}
b 模板形参表不能少
int compare(int v1,int v2)
{
return 0;
}//这种定义是错误的 ,编译器并不认为它是特化函数
3)现在来看一下特化函数的调用过程(不同的编译器下面的调用方式可能不同,这是在13版下测出的结果)
compare const <char* &>(p1, p2);
//因为他的参数和特化函数参数列表完全匹配,而且加了特化定义的模板形参所以会调用特化函数
compare(p1, p2);//但是在10 版的编译器下面调用的是特化函数
他的函数参数和特化函数参数相同,但是没写特化定义的模板形参,所以它调用的仍然是模板函数
它的实参和特化定义的模板函数形参类型不同,所以编译器会根据她的实参推演然后实例化出一个新的模板函数
注意
1)在模板特化版本的调用中,实参类型必须与特化版本函数的形参类型完全匹配, 如果不匹配,编译器将为实参模板定义中实例化一个实例。
2)特化不能出现在模板实例的调用之后,应该在头文件中包含模板特化的声明,然 后使用该特化版本的每个源文件包含该头文件。
模板类
之前我们写过顺序表,其中所放的是数字,那么现在如果想要让它可以放置任何类型的数据(int/double/char/float……)该怎么写呢?由于学习过模板函数,我们自然便想到了模板类
1 模板类的定义格式
首先,模板类也是模板,所以必须以关键字template开头
template
当我们进行test1函数调用的时,编译器会分别把T换成int double重新生成函数,
这时我们会突然想那能不能放String呢?
于是我们又定义了一个String类(这个写过很多次,就不再写了)只是我们在调用的时候会发现Seqlist总是会失败,但是自我感觉代码的逻辑是正确的,我们单不调试发现崩溃的总是这一块,代码如下
只看代码,貌似并没有问题,观察一下内存
void CheckCapacity()
{
if (_size >= _capacity)
{
T*tmp = new T[_capacity * 2];
memcpy(tmp, _pdata, _capacity*sizeof(T));
delete[]_pdata;
_pdata = tmp;
_capacity *= 2;
}
}
具体原因用画图解释比较清楚,其实也就是memcpy的时候执行了浅拷贝,所以此处应该改成深拷贝
代码实现如下
for(int i=0;i<size;i++)
{
tmp[i]=_pdata[i];
}
delete []_pdata;