C++—全特化和偏特化

全特化和偏特化

C++中的模板分为类模板和函数模板,虽然它引进到C++标准中的时间不是很长,但是却得到了广泛的应用,

这一点在STL中有着充分的体现。目前,STL在C++社区中得到了广泛的关注、应用和研究。理解和掌握模板

学习、应用和研究以及扩充STL的基础。而STL模板实例中又充斥着大量的模板特化和偏特化。

模板特化分为两种:

全特化和偏特化

首先我们得先明白一个问题,为什么会有特化这种东西呢?

因为编译器认为,对于特定的类型,如果你能对某一功能更好的实现,那么就该听你的。

全特化:

那我们就用一个例子开始吧:

[cpp] view plain copy

  1. template<class T>
  2. class A
  3. {
  4. public:
  5. A()
  6. :a(0)
  7. {}
  8. ~A()
  9. {
  10. cout << "这里走了原始的模板"<< endl;
  11. }
  12. protected:
  13. T a;
  14. };
  15. template<>
  16. class A<int>
  17. {
  18. public:
  19. A()
  20. :a(0)
  21. {}
  22. ~A()
  23. {
  24. cout << "这里走了全特化后int的版本" << endl;
  25. }
  26. protected:
  27. int a;
  28. };
  29. void test2()
  30. {
  31. A<char> a;
  32. A<int> b;
  33. }

我们先看看程序运行的结果:

我们通过析构函数发现了,A<int> b 走的是我们特化的版本。 而A<char> a走的是原始版本。

这就是全特化,我们对模板的所有参数进行了特化。如果你想学习C/C++可以来这个群,首先是三三零,中间是八五九,最后是七六六,里面有大量的学习资料可以下载。

下面是我调试时实例化b的时候,发生的事情,程序走的是int类型特化版本,有图有真相:

偏特化:

所谓的偏特化也称局部特化,大家大概明白什么回事了吧。 全特化是所有的模板参数都被进行特化

,偏特化也就是局部的参数特化,看看下面这个例子吧:

[cpp] view plain copy print?

  1. template <typename T1, typename T2>
  2. class Data
  3. {
  4. public:
  5. Data();
  6. private:
  7. T1 _d1;
  8. T2 _d2;
  9. };
  10. template <typename T1, typename T2>
  11. Data<T1, T2>::Data()
  12. {
  13. cout << "Data<T1, T2>" << endl;
  14. }
  15. // 局部特化第二个参数
  16. template <typename T1>
  17. class Data <T1, int>
  18. {
  19. public:
  20. Data();
  21. private:
  22. T1 _d1;
  23. int _d2;
  24. };
  25. template <typename T1>
  26. Data<T1, int>::Data()
  27. {
  28. cout << "Data<T1, int>" << endl;
  29. }
  30. void test2()
  31. {
  32. Data<double, int> d1;
  33. Data<int, double> d2;
  34. }
  35. int main()
  36. {
  37. test2();
  38. system("pause");
  39. return 0;
  40. }

我们观察输出的结果:

我画一张图帮我们理解吧:

下面我再举个例子,你们说说他是偏特化还是全特化:

[cpp] view plain copy print?

  1. template <typename T1, typename T2>
  2. class Data <T1*, T2*>
  3. {
  4. public :
  5. Data();
  6. private :
  7. T1 _d1 ;
  8. T2 _d2 ;
  9. T1* _d3 ;
  10. T2* _d4 ;
  11. };
  12. template <typename T1, typename T2>
  13. Data<T1 *, T2*>:: Data()
  14. {
  15. cout<<"Data<T1*, T2*>" <<endl;
  16. }
  17. // 局部特化两个参数为引用
  18. template <typename T1, typename T2>
  19. class Data <T1&, T2&>
  20. {
  21. public :
  22. Data(const T1& d1, const T2& d2);
  23. private :
  24. const T1 & _d1;
  25. const T2 & _d2;
  26. T1* _d3 ;
  27. T2* _d4 ;
  28. };
  29. template <typename T1, typename T2>
  30. Data<T1 &, T2&>:: Data(const T1& d1, const T2& d2)
  31. : _d1(d1 )
  32. , _d2(d2 )
  33. {
  34. cout<<"Data<T1&, T2&>" <<endl;
  35. }

记住这些都是偏特化,这里就要再引出一个概念,偏特化并不仅仅是指特殊部分参数,而是针对模板参数更

进一步的条件限制所设计出来的一个特化版本。

最后我在说一个注意事项: 模板的全特化和偏特化都是在已经定义的模板基础之上的,不能单独存在。

时间: 2024-10-31 09:29:44

C++—全特化和偏特化的相关文章

C++模板之特化与偏特化详解_C 语言

前言 说到C++模板,这个已经不是什么新东西了,自己在实际开发中也用过:对于C++模板特化和偏特化,对于别人来说,已经不是什么新东西了,但是对于我来说,的确是我的盲区,那天在群里讨论这个问题,自己对于这部分确实没有掌握,又联想到在<STL源码剖析>一书中,对于此也是有着介绍.所以,今天就对此进行详细的总结,以备后忘. C++模板 说到C++模板特化与偏特化,就不得不简要的先说说C++中的模板.我们都知道,强类型的程序设计迫使我们为逻辑结构相同而具体数据类型不同的对象编写模式一致的代码,而无法抽

C++模板的特化详解(函数模版特殊,类模版特化)

模版与特化的概念 函数模版与类模版 C++中模板分为函数模板和类模板 函数模板:是一种抽象函数定义,它代表一类同构函数. 类模板:是一种更高层次的抽象的类定义. 特化的概念 所谓特化,就是将泛型的东东搞得具体化一些,从字面上来解释,就是为已有的模板参数进行一些使其特殊化的指定,使得以前不受任何约束的模板参数,或受到特定的修饰(例如const或者摇身一变成为了指针之类的东东,甚至是经过别的模板类包装之后的模板类型)或完全被指定了下来. 模板特化的分类 针对特化的对象不同,分为两类:函数模板的特化和

VC类中定义静态常量

在C++类中定义常量,有以下两种方法:1.在类定义体内定义枚举常量; 例如: class A { public: enum { THREAD_NUM = 100, MEM_BLOCK_SIZE = 1024, PORT = 8080 }; }; 这样定义出来的常量值在程序运行过程中是不能被修改的,编译的时候就已经确定了这些常量的值; 2.在类定义体中声明使用static const来修饰成员常量,然后在类定义体外对这些成员进行初始化;也就是说在类定义体内定义const类型的静态成员常量; 例如:

C++类模板的三种特化

说起C++的模板及模板特化,相信很多人都很熟悉,但是说到模板特化的几种类型,相信了解的人就不是很多.我这里归纳了模板特化的几种类型,一是特化为绝对类型:而是特化为引用,指针类型:三是特化为另外一个模板类. 这里用一个简单的例子来说明这三种情况: // general version template<class T> class Compare { public: static bool IsEqual(const T& lh, const T& rh) { return lh

解读C++编程中类模板的三种特化_C 语言

1.类模板显式特化为了进行特化,首先需要一个通用的版本,称主模板.主模板使用了标准库堆算法.  堆 是一种线性化的树形结构,将一个值压入一个堆中, 实际上等于将该值插入到一个树形结构中;将一个值从堆中取出就等于移除并返回堆中最大值.但在处理字符的指针时会碰钉子.堆将按照指针的值进行组织. 我们可以提供一个显式特化版本解决此问题(例1)如果希望除了一个针对const char*的Heap外,还希望提供一个针对char *的Heap;(例2) //主模板 template <typename T>

泛型编程深入探索(一) 模版高级特性小结

一些基本的模版特性: 非类参数模版 模版所声明的参数可以不是类参数,可以声明的非类参数包括整数(double,float不可以),enum,对象引用或指针. 通过模版嵌套实现类或非类参数载类方法参数上的重载(调用时实现,不在定义时实现) 友元函数模版: 直接举例: template <typename T> friend ostream& operator<< <T>(ostream& os, const T& t){}; 内联模版函数: 模版定

【C++】模板总结

模板 模板是一种泛型编程的机制,也是一种复用的手段. //模板函数的格式: template<class 形参1,... ,class 形参n> 返回值 fun(参数列表) {...} //模板类的格式: template<class 形参1,... ,class 形参n> class A {...}; 如何实例化 编译器调用模板函数时,编译器会根据实参的类型,推演出模板的类型,并再生产相应的代码. A<int> a; //类只能显式实例化,没法推演. fun<i

仿函数、绑定、桥接、委托相关讨论

仿函数.绑定.桥接.委托相关讨论: 以下随便讨论下,没突出的中心论点,个中理论只代表我个人观点,难免有错:),欢迎指正. 一.需求: 在事件处理常常会碰到这样的情况: 1.接口分离.即invokers(调用者)与(receivers)接收者分离. 2.时间分离. 比如说:UI相关元素(按钮.菜单等)就是一个invokers. receivers则是响应命令的对象(如对话框或应用程序本身). 这需要我们要先将UI相关元素的事件响应的接收者在初始化时先保存起来. 待后用户按下按钮等再触发(即invo

Hadoop中Partition深度解析

旧版 API 的 Partitioner 解析 Partitioner 的作用是对 Mapper 产生的中间结果进行分片,以便将同一分组的数据交给同一个 Reducer 处理,它直接影响 Reduce 阶段的负载均衡.旧版 API 中 Partitioner 的类图如图所示.它继承了JobConfigurable,可通过 configure 方法初始化.它本身只包含一个待实现的方法 getPartition. 该方法包含三个参数, 均由框架自动传入,前面两个参数是key/value,第三个参数