致前行的人:
要努力,但不要着急,繁花锦簇,硕果累累都需要过程!
目录
前言:
1.非类型模板参数
1.1.概念:
1.2.使用注意事项
2.模板特化
2.1函数模板特化
2.2类模板特化
3.模板的分离编译
3.1什么是分离编译?
3.2模板的分离编译
4.模板总结
前言:
本章内容介绍的基于模板初阶之上补充介绍一些新的模板特性的内容,相信看完本章内容,关于模板,你又会有一个重新的认识和理解!
1.非类型模板参数
1.1.概念:
用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。
举例:定义一个静态数组:
#define N 10
template <class T>
struct array
{
private:
T* _a[N];
};
int main()
{
array<int> a1;
array<double> a2;
return 0;
}
这段代码中定义了a1和a2的对象,数组大小用宏来控制,但是想要定义两个对象而且大小不同就无法用这种方式实现,此时就可以引入一种非类型模板参数来控制:
template <class T,size_t N>//N就是一个非类型模板参数
struct array
{
private:
T* _a[N];
};
int main()
{
array<int,10> a1;
array<double,100> a2;
return 0;
}
1.2.使用注意事项
非类型模板参数必须是整型常量
2.模板特化
2.1函数模板特化
class Date
{
public:
friend ostream& operator<<(ostream& cout, const Date& d);
Date(int year = 2023, int month = 1, int day = 8)
:_year(year),
_month(month),
_day(day)
{}
bool operator <(const Date& d) const
{
return (_year < d._year) ||
(_year == d._year && _month < d._month) ||
(_year == d._year && _month == d._month && _day < d._day);
}
bool operator >(const Date& d) const
{
return (_year > d._year) ||
(_year == d._year && _month > d._month) ||
(_year == d._year && _month == d._month && _day > d._day);
}
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& cout, const Date& d)
{
cout << d._year << "-" << d._month << "-" << d._day;
return cout;
}
// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{
return left < right;
}
关于第三种情况不能按照上述的模板进行比较,这个时候就可以单独针对这是案例写一个模板:
2.2类模板特化
1.全特化:
2.半特化/偏特化
参数类型进一步限制:
3.模板的分离编译
3.1什么是分离编译?
一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。
3.2模板的分离编译
//a.h
template<class T>
T Add(const T& left,const T& right)
//a.cpp
#include"a.h"
template<class T>
T Add(const T& left,const T& right)
{
return left + right;
}
//main.cpp
#include"a.h"
int main()
{
Add(10,20);
}
分析:
C/C++程序要运行,一般要经历下面四个步骤:
预处理->编译->汇编->链接
编译阶段:对程序按照语言特性进行词法,语法,语义分析,错误检查无误后生成汇编代码,注意头文件不参与编译,编译器对工程中的多个源文件是分开单独编译的。
链接:将多个.obj文件合并成一个。
在a.cpp中,编译器没有看到对Add函数模板实例化,因此不会生成对应的加法函数
在main.cpp中,调用Add函数,链接的时候寻找地址,但是这个函数没有实例化生成具体代码,找不到地址,因此链接的时候会报错。
解决方案:
声明和定义不要分离!
4.模板总结
【优点】
1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
2. 增强了代码的灵活性
【缺陷】
1. 模板会导致代码膨胀问题,也会导致编译时间变长
2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误