【C++初阶】模板进阶
🥕个人主页:开敲🍉
🔥所属专栏:C++🥭
🌼文章目录🌼
1. 非类型模板参数
模板参数分为类型参数和非类型参数。
类型参数:出现在模板参数列表中,跟在class或者typename之类的参数类型名称后。
非类型参数:使用一个常量作为模板的参数,在类模板中将该参数视为常量使用。
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <assert.h>
using namespace std;namespace gjk
{//N就是非类型模板参数,用于定义数组的长度
template<class T, size_t N = 10>
class array
{
public:
array()
{
_size = 0;
}void push_back(const T& data)
{
_array[_size++] = data;
}size_t size()
{
return _size;
}
T& operator[](size_t index)
{
return _array[index];
}const T& operator[](size_t index) const
{
return _array[index];
}bool empty()
{
return _size == 0;
}
private:
T _array[N];
size_t _size;
};
}
int main()
{
gjk::array<int> a1;a1.push_back(1);
a1.push_back(2);
a1.push_back(3);
a1.push_back(4);
a1.push_back(5);cout << a1[0] << endl;
cout << a1[1] << endl;
cout << a1[2] << endl;
cout << a1[3] << endl;
cout << a1[4] << endl;return 0;
}
注意:
① 浮点数、类对象以及字符串不允许作为非类型模板参数
② 非类型的模板参数必须在编译时就能确定
2. 模板的特化
2.1 特化的概念
通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些
错误的结果,需要特殊处理,比如:实现了一个专门用来进行小于比较的函数模板:
这里我们Max函数是比较left和rihgt的值,判断left的值是否大于right的值。第一个Max(1,2)就是比较值的大小。而下面的Max(x,y)则是比较的x和y的地址大小,这显然是不符合我们的要求的。这时候我们就可以使用特化,让x和y也能够比较值的大小。
2.2 函数模板特化
函数模板的特化步骤:
① 必须要有一个基础的函数模板,也就是必须要有一个特化的对象。
② 关键字template后接一对空的<>
③ 函数名后跟一对<>,里面是需要特化的类型
④ 函数形参列表:函数形参列表必须要和函数模板一样
2.3 类模板特化
2.3.1 全特化
全特化即是将模板参数列表中所有的参数都确定化。
2.3.2 偏特化
偏特化:任何针对模版参数进一步进行条件限制设计的特化版本。比如对于以下模板类:
template<class T1,class T2>
class Max
{
public:
void Printf()
{
cout << "<T,T>" << endl;
}private:
T1 _a;
T2 _b;
};//偏特化char,只要传的第二个参数为char,不管第一个是什么类型,都进这个类
template<class T>
class Max<T, char>
{
public:
void Printf()
{
cout << "<T,char>" << endl;
}private:
int _a;
char _b;
};//偏特化int,只要传的第一个参数是int,不管第二个是什么类型,都走这个类
template<class T>
class Max<int, T>
{
public:
void Printf()
{
cout << "<int,T>" << endl;
}private:
int _a;
char _b;
};//篇特化double,只要传的第二个参数是double,不管第一个是什么类型都走这个
template<class T>
class Max<T, double>
{
public:
void Printf()
{
cout << "<T,double>" << endl;
}private:
int _a;
char _b;
};
3. 模板分离编译
3.1 什么是分离编译
一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有
目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。
3.2 模板的分离编译
假如有以下场景,模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义:
// a.h
template<class T>
T Add(const T& left, const T& right);
// a.cpp
template<class T>
T Add(const T& left, const T& right)
{
return left + right;
}// main.cpp
#include"a.h"
int main()
{
Add(1, 2);
Add(1.0, 2.0);
return 0;
}
3.3 解决方法
① 将声明和定义放到一个文件 "xxx.hpp" 里面或者xxx.h其实也是可以的。推荐使用这种。
② 模板定义的位置显式实例化。这种方法不实用,不推荐使用。
4. 模板总结
优点:
① 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生。
② 增强了代码的灵活性。
缺点:
① 模板会导致代码膨胀问题,也会导致编译时间变长。
② 出现模板编译错误时,错误信息非常凌乱,不易定位错误。
创作不易,点个赞呗,蟹蟹啦~