模板进阶&&模板分离编译的问题与解决

🧸🧸🧸各位大佬大家好,我是猪皮兄弟🧸🧸🧸
在这里插入图片描述

一、模板参数

模板参数分为类型形参与非类型形参
类型形参:出现在模板参数中,跟在class或者typename之后的参数类型名称
非类型形参:就是一个常量作为类模板/函数模板的一个参数,在类模板/函数模板中可将该参数当成常量来使用

1.非类型模板参数

template<class T,size_t N=100>//缺省参数
class Array
{
private:
	T _a[N];
}

需要注意的是:浮点数、类对象以及字符串是不允许作为非类型参数的。也就是说,非类型模板参数只允许是整形家族(char类型也算在整形家族),而且非类型模板参数是在编译阶段就要能确定。

比如库中的array

库中的array

template<class T,size_t N> class array;

2.类型模板参数

这个就简单提一下吧,平时正常用的就是这个

template<class T>
class Node
{
	//...
private:
	T data;
	Node<T> *_next;
}

二、模板参数的特化

特化就是特殊化
通常情况下,使用模板可以处理一些类型无关的代码,但对一些类型可能会得到一些错误的结果,需要特殊处理,比如:我想实现一个进行小于比较的函数模板,但是对于某些类型,它的行为不是我想要的,针对某些类型进行特殊化处理

template<class T>
bool Greater(T left,T right)
{
	return left>right;
}
template<>
bool Greater(Date* left,Date* right)//是一个日期类
{
	return *left>*right;//日期类中重载了operator>
}

再比如后面学哈希的时候,一些哈希函数处理某些类型也需要用到特化,比如哈希函数处理字符串。

特化不能单独使用,特化必须是对已有的模板进行特化。
有特化就用特化,没有编译器就会去按模板推演实例化出新的

1.全特化

template <class T1,class T2>
class Date
{
  ....  
};
template<>
class Date<int,char>
{
    ....
}

2.偏特化(半特化)

template<class T1,class T2>
class Date
{
    ....
}
template<class T1>
class Date<T1,int>
{
    ...
}
template<class T1,class T2>
class Date<T1*,T2*>//这也是偏特化
{
    ...
}
template<class T1,class T2>
class Date<T1&,T2&>//这也是偏特化
{
    ....
}

三、模板的分离编译的问题

分离编译是指的,模板的声明放在头文件,定义放在源文件

1.模板的分离编译书写很麻烦

比如现在我分离编译了模拟实现的vector

//定义的时候
template<class T>
typename vector<T>::iterator vector<T>::insert(typename vector<T>::iterator pos,const T&x)
{
	//...
}

这是遇到的模板中typename和class的第一个区别,这里是因为vector::成员,它不知道你要去访问静态成员还是iterator这个类型。加上typename就是为了告诉编译器vector::iterator是一个类型,不然的化就有二义性,因为静态成员也是这样访问的

2.模板的分离编译有声明但找不到定义

解释:生成目标文件之前,头文件的内容早在预编译阶段就被展开到了源文件当中,但是其他的都能链接的上,唯独模板分离编译的链接不上,原因就是模板分离编译的东西没有被实例化(链接之前,多个源文件并不会交汇,比如说我有vector.hpp vector.cpp和test.cpp,test.cpp和vetcor.cpp包含头文件vector.hpp,预编译阶段,vector.hpp展开到了两个源文件当中。但是在编译阶段,在vector.i中并不会去对模板进行编译,因为没有人告诉他准确的T类型)所以在链接阶段链接的时候,只有声明没有定义,链接的时候去符号表中找,找不到,链接错误,问题就出在编译阶段没有被实例化

所以提倡模板声明和定义不分离(分离是指的在两个文件当中,因为两个源文件不会交互,模板的准确类型得不到),小函数应该放在类中称为内联,大函数应该在类外定义,因为类里只有声明的话就可以更好的看到整个的框架

3.模板分离编译的解决办法

解决办法就是显示实例化,但是显示实例化时把类型写死了,所以非常不推荐

//在分离编译的地方给给定义
template
vector<int>;

template
vector<double>;

显示实例化可以有多个

四、模板总结

优点

1.模板服用了代码,节省资源,更快的迭代开发,C++标准模板库因此而产生
2.增强代码的灵活性,重复的事情交给 编译器做

缺点

1.模板会导致代码膨胀问题(inline之所以是建议性关键字的问题也是内联会代码碰撞),也会导致编译时间变长
2.出现模板编译错误时,错误信息非常凌乱,不易定位错误

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

猪皮兄弟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值