C++--模板进阶

一、非类型模板参数

在这里插入图片描述
我们先来举一个例子:
在这里插入图片描述
当我们用宏去控制同种类型数组的大小时,无法做到完全的统一,总会有浪费或是不够。
此时我们的非类型模板参数就发挥作用了
在这里插入图片描述

Tips:
1.通常给非类型模板参数赋缺省值,这样开辟一个数组就无比的方便了
2.这里的非类型模板参数赋值时,仅可为整数

二、模板的特化

首先回顾一下模板的概念:模板就是编译器自动给我实例化出一份符合逻辑的代码。但是总有些情况,编译器无法给出正确的逻辑。

在这里插入图片描述

比如此时:当我们比较P1和P2这两个字符数组时,我们发现结果并不是相等的,而字符串常量p3和p4是相同的
原因:
首先字符常量存在于进程地址空间的常量区,并且只存在一份。本质我们p3和p4指向的是同一个空间地址。而编译器在实例化的时候,T实例化为指针的右值。显然是相等的。
然而字符数组在栈上开辟了两个完全不同的空间,实例化时也是实例出数组指针。很明显此时两个数组的地址是不同的。所以得到这种结果。
我们想要比较两个字符串是否相等,应该采用strcpy这样的函数来比较字符的ascll值,而不是指针。所以这里的实例化就不尽人意。
此时模板特化就来发挥作用了。


模板特化有很多种方式,我们先来看看函数模板的特化
在这里插入图片描述
在这里插入图片描述
我们不给模板参数,直接进行特化,这样这份代码就会自动优先匹配这个已经被我们特化后的函数。

我们再来看看类模板的 特化
在这里插入图片描述
这两个类实例化后结果显而易见,会与最匹配的模板进行匹配实例化。

以上介绍的都是全特化,我们还有偏特化的概念,意义也很清楚,就是不全部特化。
在这里插入图片描述
这里为什么d1不匹配偏特化呢?这里的设计为:先匹配全特化,在匹配偏特化,最后匹配无特化。

除了这些内置类型的特化,还有指针特化 引用特化

在这里插入图片描述
如果此时变量类型为指针或是引用,就直接实例化特化的类。如果一个为指针,一个为引用,那么就回去匹配没有特化的原生类,前提是你没有专门特化出一个(*,&)这样的类。

匹配优先度最高的


三、模板不支持分离编译

当我们将模板的声明和定义分开,一个放在.h一个放在.cpp中,那么此时会发生链接错误
在这里插入图片描述
在这里插入图片描述
原因:
我们在讲底层逻辑之前,先来背诵一下c语言编译过程
1.预处理:头文件展开,条件编译,宏替换,去注释等
2.编译:将.c代码翻译成汇编代码,同时生成符号表,并检查语法错误
3.汇编:将汇编代码生成二进制文件
4.链接:动静态链接 ,多文件链接


此时我们可以发现,链接错误一定是发生在最后一步。
编译过程:main.i -->main.s 时,我们的main函数会去调用add函数
这时候会根据函数名命名规则:比如我们的add函数
call _Z3Addii(?) 括号中是函数的地址,但是由于我们分离编译,main函数中只能确定函数名,检查参数匹配等语法问题,在链接的时候,才会找到这个地址。
由于我们的模板定义在其他文件,就造成我们在main函数中一直没有类模板的定义,而只有声明,无法实例化。有定义的地方我们没法实例化,因为实例化过程发生在编译阶段,有定义的地方在链接阶段。而当到了链接的时候,尽管有了定义,由于实例化阶段已经过了,编译器就会报连接错误。

解决方法:
1.显式实例化
在这里插入图片描述
这样很不推荐,用一个实例化一个。

2.推荐:不要分离编译,实例化的地方给定义

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值