时间:2014.01.16
地点:基地——终于搬回基地实验室了,好冷啊!
——————————————————————————————————
一。简述
通常来说,常规的模板具有很高的通用性,对各种数据类型都适用,就像通用计算机。但有时针对某一数据类型,我们需要特殊处理,于是我们不得不针对这一特定数据类型专门打造,但对于用户来说,看起来又都一样,因此我们需要对类模板进行特化。当然函数模板也可以特化。另外类模板的实例化有一个潜在问题,就是代码膨胀。每实例化一次,实例化的代码段就会被添加到程序代码空间来,使用类模板特化技术可以有效减少代码膨胀的问题。
二、基本概念
主类模板,通俗来讲,就是那个最通用,泛化最强的模板。
完全特化:也称绝对特化,即直接对某一具体类型做特殊化处理。
部分特化:顾名思义,只特殊化部分参数,比如类型的某种特征:指针形式或者引用形式等
三、实例
下面模板类使用容器构建一个栈Stack,首先我们构建一个主类模板,所有模板的特化工作也是在该主类模板的基础上进行的。
template<typename T> class Stack{ private: vector<T> elems; public: void push(const T &item){ elems.push_back(item); } void pop(){ if (elems.empty()) return; elems.pop_back(); } T top() const{ if (elems.empty()) return NULL; return elems.back(); } };现在我们想对模板特殊化一点,即当模板参数为string类型时,我们并不想要和上述一样的行为,比如我们想要用deque容器来实现存放元素,在这个代码段中,特化模板只针对这一个具体的类型。属于完全特化,完全特化首行的尖括号内容须为空。
template<> class Stack<string>{ private: deque<string> elems; public: void push(const string &item){ elems.push_back(item); } void pop(){ if (elems.empty()) return; } string top() const{ if (elems.empty()) return NULL; return elems.back(); } };
有时,我们也并不需要完全特化,而是就某一类型的某种特征而做特殊处理,比如我们想要T*做点特殊处理,那么行首尖括号中的T还是必须的,但后面参数须加上对T*的声明,以此表明当类型为T*时,我们不是采用主类模板的代码。一下是用list来存储对象的部分特例化实例
template<typename T> class Stack<T*>{ private: list<T*> list; public: void push(T* &item){ list.push_front(item); } void pop(){ if (list.empty()) return; list.pop_front(); } T* top() const{ if (list.empty()) return NULL; return list.front(); } };
四、总结
当模板参数满足一些特殊条件时,我们使用特殊化模板来实例化,编译器会更具匹配精确度优先匹配精确度更高的实现,对于一般情形,任然使用主类模板进行实例化,一句话,特殊情况特殊处理,普通情况一般处理。