🧸🧸🧸各位大佬大家好,我是猪皮兄弟🧸🧸🧸
文章目录
- 一、模板参数
- 1.非类型模板参数
- 比如库中的array
- 2.类型模板参数
- 二、模板参数的特化
- 1.全特化
- 2.偏特化(半特化)
- 三、模板的分离编译的问题
- 1.模板的分离编译书写很麻烦
- 2.模板的分离编译有声明但找不到定义
- 3.模板分离编译的解决办法
- 四、模板总结
- 优点
- 缺点
一、模板参数
模板参数分为类型形参与非类型形参
类型形参:出现在模板参数中,跟在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.出现模板编译错误时,错误信息非常凌乱,不易定位错误