目录⭐️今天我要给大家介绍C++中的模板更深的一些知识。有关于非类型的模板参数和模板特化的一些知识。
⭐️博客代码已上传至gitee:https://gitee.com/byte-binxin/cpp-class-code
非类型模板参数模板的特化
函数模板的特化类模板的特化 模板的分离编译总结
非类型模板参数
模板参数分类类型形参与非类型形参。
类型模板形参:出现在模板参数列表中,跟在class或者typename后面的参数类型名称。(这个我们之前有讲过)非类型模板形参:用一个常量作为模板的一个参数,必须是整形家族中的类型参数,否则不行。他在模板中可以当常量使用。
实例:
// 类型模板参数namespace wxj{// 非类型模板参数 N 是一个常量参数,只能是整形家族的:int short char long long long 自定义类型和其他类型都不能作费类型模板参数// 必须在编译期就能确认结果template
代码运行结果如下:
看上面,我们定义了一个数组类,空间大小由N决定,类型是Array
注意:
非类型形参必须是整形家族中的类型,浮点数和类对象都不行。非类型的模板形参必须在编译期间就能确认结果。 模板的特化函数模板的特化模板特化:在原模板类的基础上,针对特殊类型所进行的特殊化的实现。分为函数模板特化 和类模板特化。
特化的步骤
必须先有一个基础的函数模板关键字template后面接一对空的尖括号<>函数名后跟一对尖括号<>,里面指定需要的特化的类型函数形参列表:必须和函数模板的基础参数类型完全一致实例
// 模板的特化 模板的特殊化template
注意: 一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将该函数直接给出。
bool IsEqual(char* left, char* right){return strcmp(left, right) == 0;}
类模板的特化类模板的特化分为全特化和偏特化。
全特化: 对类模板参数列表的类型全部都确定(明确指定)
template
偏特化: 堆类模板的参数列表中部分参数进行确定化分为部分特化和参数进一步限制
部分特化// 部分template
// 参数进一步限制 堆模板参数更进一步的条件限制template
实例 我们试着实例化几个对象,看他们用的是哪个模板
int main(){Date
代码运行结果:
分离编译: 我们对这个应该是不陌生的,就是把函数的声明放在一个叫**.h的文件中,实现都放在一个叫.cpp**的文件中,这样方便我们管理。
下面我们试着对模板进行分离编译:
// a.h#pragma once// 普通函数void Swap(int& a, int& b);// 函数模板template
代码运行结果如下
代码运行时发生了报错,说Add这个函数是没有见过的。得出结论:函数模板不能分离编译,普通函数可以。
为什么会这样呢?
模板在.cpp中定义了,由于不知道T的类型,所以没有对模板进行实例化。a.h 和 a.cpp 走的是两条不同的路,两条路都没有对模板进行实例化(因为不知道T的类型)。因为没有对模板进行实例化,所以没有函数参数,也就没有函数地址,所以在链接时,test.cpp中的调用Add函数时,没有函数地址,call调用不到Add函数,所以报错。C++程序运行一般经过几个阶段:预处理——>编译——>汇编——>链接(更详细的内容可以参考往期博客——程序的编译)
解决方法:
暴力:不分离编译,统一放在一个.h或.hpp的文件中模板定义位置显示实例化(不推荐,这样就失去了泛型的特点) 总结 模板进阶也就是这些内容了,喜欢的话,欢迎点赞、收藏和关注支持~