一、模板函数 假如要实现一个加法函数使其可以通用任何类型。 当然能通过宏来实现 #define Add(a,b) ( (a)+(b) ) 但是宏的缺点显而易见。不能进行参数检测,安全性太差了。 还可以写出一下的函数模板。
template<class T>//模板的参数列表 T Add(T left, T right) { return left + right; }当然单单以上的模板是编译不能通过的。因为会发现有链接错误,也就是系统找不到实例,只是一个模板 ,从而链接错误。 加入函数的实例化就可编译通过:
int main() { int sum=0; sum=Add(1,2);//实例化,也叫推演 return 0; }实例化可以分为显示和隐式。
Add<int>(1,2)//显式 Add(1,2)//隐式【参数类型转换】 编译器只会转换以下情况下的: 1.const 引用或者const 修饰的指针 可以分别用非const的引用和非const 的指针来调用。 2.数组名会被转化为指针。 3.函数名被转化为函数指针。 注意: 1.template里面的class 可以用typename替换 而不能用struct 替换。 2.函数模板只是一个产生函数的工具,而不是真正的函数。 3.模板被编译了两次,第一次是在模板的时候检查语法错误。第二次在实例化的时候进行编译查看参数是否调用有效。 4.inline关键字要放在模板参数列表后返回值前。例如:inline T Add(T left ,T right) 5.当该函数声明了时,编译器不会用模板来生成这个函数,而是直接调用已经有的函数。 【模板特化】 特化是对模板进行特殊化处理 可以这样写
template<> double Add< double>(double p1, double p2) { return p1+p2; }特化后,实例化的时候会先找特化版本,如果没有再用通用模板实现 二、类模板 类模板也是模板 格式为:
template<class 形参,class 形参.....> class 类名 { .... };双向链表的模板
template <class T> struct ListNode { ListNode(const T&x) :_data(x) , _next(NULL) , _prev(NULL) {} T _data; ListNode<T> *_next; ListNode<T>*_prev; }; template<class T> class List { typedef ListNode<T> Node;//方便起见 重命名该类型 public: List() :_pHead(NULL) , _pTail(NULL) {} private: Node *_pHead; Node *_pTail; };总结模板: 优点:代码复用,提高了效率, 提高了代码的灵活度。 缺点:模板让代码复杂,凌乱。编译代码时间变长,出现错误时不能准确的定位错误。