C++模板进阶

模板的特化

分全特化,偏特化(也叫半特化)
非类型模板参数也是可以特化的

使用场景:

在优先级队列中,正常情况,如果我们想要比较整形家族(例如int, char)的数据时,可以用模板来传参,就可以比较大小了。

template<class T>
struct Less
{
	bool operator()(const T& x,const T& y) const
	{
		return x < y;
	}
};

但是我想要在类里面比较较为复杂的类型时,比如日期类Date。传参就传了指针,那么,并不能达到我们比较日期的目的,所以我们需要对这个类型进行特殊化处理(特化)。

template<>
strcut Less<Data*>
{
	bool operator()(Data* x, Data* y) const
	{
		return *x < *y;
	}
};

这里是类模板特化,还有函数模板特化

模板的分离编译

首先什么是分离编译?
一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件连接起来形成单一的可执行文件的过程。

假如有以下场景,模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义:

// a.h
template<class T>
T Add(const T& x, const T& y);

// a.cpp
template<class T>
T Add(const T& x, const T& y)
{
	return x + y;
}

// test.cpp
#include"a.h"
int main()
{
	Add(1, 2);
	Add(1.0, 2.0);
	return 0;
}

但这样写可行吗?
我们知道程序运行的步骤:

a.h/a.cpp/test.cpp
生成a.i,test.i文件
生成a.s,test.s文件
生成a.o,test.o文件
预处理:删除注释,宏替换,头文件展开,条件编译
编译:检查语法,生成汇编代码
汇编:把汇编代码转化成机器码
链接将多个.o文件合并形成文件a.out

其实模板

test.cpp中,编译它调用Add()函数时,编译器只知道有一个Add()函数的声明,编译器没有看到对Add模板函数的实例化,因此不会生成具体的加法函数。
main.obj中调用的Add<int>Add<double>,编译器在链接时才会找其地址,但是这两个函数没有实例化没有生成具体代码,因此链接时报错。

在这里插入图片描述
解决方法

  1. 将声明和定义放到一个文件 “xxx.hpp” 里面或者xxx.h,也是可以的。——推荐使用这种
  2. 模板定义的位置显式实例化。—— 这种方法不实用,不推荐使用

那类模板呢?
我们使用某个类都要调用它的构造函数,所以其实类模板和函数模板在这里是一样的。

仿函数

对于排序算法来说,我们需要对不同的对象进行比较就可能需要不同的比较函数,这样才能排序。然而C语言提供的解决方法就是回调函数函数指针,说实在的比较晦涩难懂罢。到了C++我们就选择使用仿函数来解决。

看如下仿函数Less

template<class T>
struct Less
{
	bool operator()(const T& x,const T& y) const
	{
		return x < y;
	}
};

其实就是重载了( )这个运算符的一个类。

模板的优劣

复用了代码,减少重复工作,更加方便开发,STL也是因此而诞生的。
增强了代码灵活性。

导致了代码膨胀,虽然不用模板也要写这么多代码,但是容易误以为很少。也会导致代码运行时间增加(主要是模板实例化导致的)。
出现模板编译错误时,报错会变得很多,不容易定位错误(雀食)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

eptcup_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值