💙系列文章💙dzc6;个人主页:企鹅不叫的博客
🌈专栏
- 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
文章目录
- 💙系列文章💙
- 💎一、非类型模板参数
- 💎二、模板的特化
- 🏆1.函数模板的特化
- 🏆2.类模板的特化
- 2.1全特化
- 2.2偏特化
- 💎三、模板分离编译
- 🏆1.实例
- 🏆2.原因
- 🏆3.解决方法
- 💎四、模板优缺点
💎一、非类型模板参数
💎二、模板的特化模板参数分类类型形参与非类型形参。
类型模板形参:出现在模板参数列表中,跟在class或者typename后面的参数类型名称。
非类型模板形参:用一个常量(浮点数,字符串,类对象不允许作为非类型模板参数)(可以是 int short char long longlong)作为模板的一个参数,必须是整形家族中的类型参数。
template<class T =int, size_t N = 10> class array { private: T _array[N]; size_t _size; }
🏆1.函数模板的特化模板特化:在原模板类的基础上,针对特殊类型所进行的特殊化的实现。分为函数模板特化 和类模板特化。
🏆2.类模板的特化 2.1全特化
必须先有一个基础的函数模板
关键字template后面接一对空的尖括号<>
函数名后跟一对尖括号<>,里面指定需要的特化的类型
函数形参列表:必须和函数模板的基础参数类型完全一致
// 模板 template<class T> bool IsEqual(T& left, T& right) { return left == right; } // 特化 template<> bool IsEqual<const char* const>(const char* const& left, const char* const& right) { return strcmp(left, right) == 0; }
2.2偏特化对类模板参数列表的类型全部都确定
template <class T1, class T2> class Date { public: Date() { cout << "Date
" << endl; } private: T1 _d1; T2 _d2; }; // 全特化 template<> class Date<int, double> { public: Date() { cout << "Date" << endl; } private: int _d1; double _d2; };
💎三、模板分离编译 🏆1.实例偏特化:任何针对模版参数进一步进行条件限制设计的特化版本
偏特化有两种表现方式,一种是部分参数特化,一种是参数修饰特化
部分特化,模板参数类表中一部分参数特化
//第二个参数特化 template<class T1> class test<T1, double> { public: test() { cout << "test
" << endl; } private: T1 _x; double _y; }; int main() { test<double, double> t1; test<int, double> t2; }参数更进一步限制,偏特化不指是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本
//如下有T1*和T2*,是模板的类型转为指针类型和引用类型 /template<class T1, class T2> class test<T1*, T2*> { public: test() { cout << "test
" << endl; } private: T1* _x; T2* _y; }; int main() { test<int*, double*> t; }
🏆2.原因**分离编译:**C++的编译器却不支持模板的分离编译,一旦进行分离编译,就会出现链接错误,下面代码就会报错。详情看这里传送门
// a.h #pragma once // 普通函数 void Swap(int& a, int& b); // 函数模板 template<class T> T Add(const T& a, const T& b); // a.cpp #define _CRT_SECURE_NO_WARNINGS 1 #include "a.h" // 普通函数 void Swap(int& a, int& b) { int tmp = a; a = b; b = tmp; } // 函数模板 template<class T> T Add(const T& a, const T& b) { return a + b; } // test.cpp #include "a.h" int main() { int a = 3; int b = 4; Swap(a, b); cout << "a = " << a << " b = " << b << endl; cout << Add(a, b) << endl; return 0; }
🏆3.解决方法1.模板在.cpp中定义了,由于不知道T的类型,所以没有对模板进行实例化。
2.a.h 和 a.cpp 都没有对模板进行实例化,因为不知道T的类型。
3.因为没有对模板进行实例化,所以没有函数参数,也就没有函数地址,所以在链接时,test.cpp中的调用Add函数时,没有函数地址,call调用不到Add函数,所以报错。
💎四、模板优缺点
- 暴力:将声明和定义统一放在一个.h或.hpp的文件中
- 模板定义位置显示实例化(不推荐,这样就失去了泛型的特点)
【优点】
1.模板复用了代码,节省资源,更快的迭代开发
2.增强了代码的灵活性
【缺点】
1.导致编译时间变长
2.出现模板编译错误时,错误信息非常凌乱,不易定位错误
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)