🏆个人主页:企鹅不叫的博客
🌈专栏
- C语言初阶和进阶
- C项目
- Leetcode刷题
- 初阶数据结构与算法
- C++初阶和进阶
- 《深入理解计算机操作系统》
- 《高质量C/C++编程》
- Linux
⭐️ 博主码云gitee链接:代码仓库地址
⚡若有帮助可以【关注+点赞+收藏】,大家一起进步!
💙系列文章💙
【初阶与进阶C++详解】第一篇:C++入门知识必备
【初阶与进阶C++详解】第二篇:C&&C++互相调用(创建静态库)并保护加密源文件
【初阶与进阶C++详解】第三篇:类和对象上(类和this指针)
【初阶与进阶C++详解】第四篇:类和对象中(类的六个默认成员函数)
【初阶与进阶C++详解】第五篇:类和对象下(构造+static+友元+内部类
【初阶与进阶C++详解】第六篇:C&C++内存管理(动态内存分布+内存管理+new&delete)
【初阶与进阶C++详解】第七篇:模板初阶(泛型编程+函数模板+类模板+模板特化+模板分离编译)
【初阶与进阶C++详解】第八篇:string类(标准库string类+string类模拟实现)
【初阶与进阶C++详解】第九篇:vector
【初阶与进阶C++详解】第十篇:list
【初阶与进阶C++详解】第十一篇:stack+queue+priority_queue+deque
文章目录
💎一、非类型模板参数
模板参数分类类型形参与非类型形参。
- 类型模板形参:出现在模板参数列表中,跟在class或者typename后面的参数类型名称。
- 非类型模板形参:用一个常量(浮点数,字符串,类对象不允许作为非类型模板参数)(可以是 int short char long longlong)作为模板的一个参数,必须是整形家族中的类型参数。
template<classT=int, size_t N =10>classarray{private: T _array[N]; size_t _size;}
💎二、模板的特化
模板特化:在原模板类的基础上,针对特殊类型所进行的特殊化的实现。分为函数模板特化 和类模板特化。
🏆1.函数模板的特化
- 必须先有一个基础的函数模板
- 关键字template后面接一对空的尖括号<>
- 函数名后跟一对尖括号<>,里面指定需要的特化的类型
- 函数形参列表:必须和函数模板的基础参数类型完全一致
// 模板template<classT>boolIsEqual(T& left, T& right){return left == right;}// 特化template<>boolIsEqual<constchar*const>(constchar*const& left,constchar*const& right){returnstrcmp(left, right)==0;}
🏆2.类模板的特化
2.1全特化
对类模板参数列表的类型全部都确定
template<classT1,classT2>classDate{public:Date(){ cout <<"Date<T1, T2>"<< endl;}private: T1 _d1; T2 _d2;};// 全特化template<>classDate<int,double>{public:Date(){ cout <<"Date<int, double>"<< endl;}private:int _d1;double _d2;};
2.2偏特化
偏特化:任何针对模版参数进一步进行条件限制设计的特化版本
偏特化有两种表现方式,一种是部分参数特化,一种是参数修饰特化
部分特化,模板参数类表中一部分参数特化
//第二个参数特化template<classT1>classtest<T1,double>{public:test(){ cout <<"test<T1, double>"<< endl;}private: T1 _x;double _y;};intmain(){ test<double,double> t1; test<int,double> t2;}
参数更进一步限制,偏特化不指是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本
//如下有T1*和T2*,是模板的类型转为指针类型和引用类型/template<classT1,classT2>classtest<T1*, T2*>{public:test(){ cout <<"test<T1*, T2*>"<< endl;}private: T1* _x; T2* _y;};intmain(){ test<int*,double*> t;}
💎三、模板分离编译
🏆1.实例
分离编译:C++的编译器却不支持模板的分离编译,一旦进行分离编译,就会出现链接错误,下面代码就会报错。详情看这里传送门
// a.h#pragmaonce// 普通函数voidSwap(int& a,int& b);// 函数模板template<classT> T Add(const T& a,const T& b);// a.cpp#define_CRT_SECURE_NO_WARNINGS1#include"a.h"// 普通函数voidSwap(int& a,int& b){int tmp = a; a = b; b = tmp;}// 函数模板template<classT> T Add(const T& a,const T& b){return a + b;}// test.cpp#include"a.h"intmain(){int a =3;int b =4;Swap(a, b); cout <<"a = "<< a <<" b = "<< b << endl; cout <<Add(a, b)<< endl;return0;}
🏆2.原因
1.模板在.cpp中定义了,由于不知道T的类型,所以没有对模板进行实例化。
2.a.h 和 a.cpp 都没有对模板进行实例化,因为不知道T的类型。
3.因为没有对模板进行实例化,所以没有函数参数,也就没有函数地址,所以在链接时,test.cpp中的调用Add函数时,没有函数地址,call调用不到Add函数,所以报错。
🏆3.解决方法
- 暴力:将声明和定义统一放在一个.h或.hpp的文件中
- 模板定义位置显示实例化(不推荐,这样就失去了泛型的特点)
💎四、模板优缺点
【优点】
1.模板复用了代码,节省资源,更快的迭代开发
2.增强了代码的灵活性
【缺点】
1.导致编译时间变长
2.出现模板编译错误时,错误信息非常凌乱,不易定位错误
版权归原作者 企鹅不叫 所有, 如有侵权,请联系我们删除。