c++中的模板特化(辨析性质的笔记,原内容为转载,笔记为原创)

模板声明与定义的关系

好久不用C++了,前几天写了一个模版,按以前的习惯,把定义写在头文件中, 把实现写在cpp文件中。结果在编译的时候没有发生错误,但在连接的时候出现了找不到xxx的错误。一时之间不知道该怎么办才好,后来上网一查,自己再一想,唉,原来如此:

     模版之所以为模版,就是可以容纳不同的类型嘛,所以它只有在指定了其类型的时候才会生成实际的代码,如果你只把模版的声明写在头文件中,那么你生成在使用模版的时候就只会有声明部分,而没有其具体的实现,所以链接器在连接时会报错。

    解决的办法有两个:

     1. 把模版的声明和实现都写在一个头文件中,然后用的时候包含这个头文件。

     2. 如果你已经把它们分开了,比如说xxx.h xxx.cpp。那也好办,只好在使用的时候#include “xxx.h” #include “xxx.cpp”即可。


###################################################################################################

模板特化

模板是针对泛型编程的,泛型即不针对特定类型,所有类型都可以套用,而且是编译阶段由编译器完成由泛型到特定类型的转换,编译器实际上做的就是把你制定的类型替换到模板中的模板类型,然后再执行编译连接。

那么这时候会出现某种问题,当某一特定类型跟其他类型在某些操作上有不同的特性时,泛型编程这边就很难做。

举个例子,一个compare()函数:

template<typename T>

int compare(const T&v1, const T&v2)

{

if(v1 < v2) return -1;

if(v2 < v1)return 1;

return 0;

}

上面这个compare的模板实现,对int、long、float、char等类型来说都没问题,但对于指针类型如const char*类型时则有问题,因为模板函数的实现中这样比较的话,当类型被代换为const char*时,比较的是两个指针本身值的大小,而不是两个指针所指向内容的大小。

那该如何解决这个问题呢,能否写出一个模板它可以兼容常规类型(对某特定操作具有相同性质)又同时可兼容某些特定类型(对某些特定操作具有不同的性质)呢?

模板特化出场了。

模板特化有点类似函数重载的那种思想,首先写出能兼容大多数类型的模板体,然后再针对某些特定类型再重写特殊的实现体,该实现体指明了只针对这些特定类型。然后编译器在编译时,遇到模板调动后先匹配模板特化,如果模板特化未匹配中再匹配模板。这样就实现了可以自由的兼容所有类型(有多少类型跟大多数类型不一样,就实现多少个针对这些类型的模板特化)

如上面那个compare模板函数,可以实现一个针对const char*的模板特化:

//模板特化可以理解为针对模板的补充,那么自然模板(非特化模板)是不可或许的,如果没有模板放在前面,那么是不好理解模板特化的意义的

//(因为你如果不知道特化是针对模板的补充的话,你完全有理由问“为什么不干脆声明为普通函数呢,这个模板既然已经指定了类型,那还有啥作用?”

template<typename T>

int compare(const T&v1, const T&v2)

{

if(v1 < v2) return -1;

if(v2 < v1)return 1;

return 0;

}

//对compare函数的一个特化

template<>

int compare<const char*>(const char* const &v1, const char* const &v2)

{

return strcmp(v1, v2);

}

注意,特化的声明必须与对应的模板完全匹配。

有了函数模板的特化,自然也有类模板的特化。二者差别不大,不过要说一下的是如果需求中需要特化某类模板,可以考虑将真个类模板特化,也可以考虑将只该类模板中某些必须特化的接口给特化(部分特化),如vector和queue容器针对const char*类型时所作的特化,可以仅特化push和pop两函数。

另外,若某模板有多个模板形参,那么将它全部的形参都特化这种方式称为全特化,将它的部分形参特化的方式称为偏特化。

如这里:

template<class U,class T>
class C{};
全特化:
template<>
class C<int,char>{};
偏特化:
template<class U>
class C<U,int>{};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值