系列文章目录

上篇文章:【C++闯关笔记】STL:deque与priority_queue的学习和使用-CSDN博客

下篇文章:【C++闯关笔记】深究继承-CSDN博客


文章目录

目录

系列文章目录

文章目录

前言

一、非类型模板参数介绍

二、模板特化

1.函数模板特化

2.类模板特化

1)全特化

2)偏特化

总结



前言

【C++闯关笔记】封装②:友元与模板_c++封装,友元-CSDN博客 一文中,我们讨论了函数模板的基本用法,并明确了模板是泛型编程的基础。

本文在模板的基础用法之上,介绍什么是模板的特化。


一、非类型模板参数介绍

模板参数分 类类型形参非类型形参

在一些C++教材上一般只介绍类类型模板参数,而非类型模板参数却少有提及。

类类型形参:即出现在模板参数列表中,跟在class或者typename之类的参数类型名称。如下文代码中的 T 类型。

template<typename T>
 void swap( T& left,  T& right)
 {
 T temp = left;
 left = right;
 right = temp;
 }

非类型形参:就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。如下文代码中的 size_t N 。

//一个静态定长数组
template<class T,size_t N =10>
class Array
{
public:
	T& operator[](size_t pos)
	{ 
		return _array[pos];
	}
	bool empty()
	{
		return _size == 0;
	}
	size_t size()const
	{
		return _size;
	}
private:
	T _array[N];
	size_t _size;
};

非类型模板参数常与类类型模板参数一起使用,但非类型模板参数有些细节需要注意:

浮点数、类对象以及字符串是不能作为非类型模板参数的。

二、模板特化

模板可以实现不同类型的数据使用同一套代码实例化,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊处理。

比如下面代码中,将地址传给函数Less就会造成错误。

template<class T>
bool Less(T left, T right)
{
    return left < right;
}

int main()
{
    int a = 1,b = 2;
    Less(a,b);//正确
    Less(&a,&b);//错误
    return 0;
}

此时就需要特殊处理。

1.函数模板特化

特化,翻译一下就是特殊的实例化,即在原模板类的基础上,针对特殊类型所进行特殊化的实现方 式。

特化的步骤:

①. 已经有了一个基础的模板;

②. 关键字template后面接一对空的尖括号<>

③. 函数名/类名后跟一对尖括号,尖括号中指定需要特化的类型。

④. 函数形参表: 必须要和模板函数的基础参数类型完全相同。

就拿上面的Less模板函数,特化处理指针作为示例:

// 函数模板 -- 参数匹配
 template<class T>
 bool Less(T left, T right)
 {
 return left < right;
 }
 // 对Less函数模板进行特化
 template<>
 bool Less<Date*>(Date* left, Date* right)
 {
 return *left < *right;
 }

2.类模板特化

1)全特化

全特化:将模板参数列表中所有的参数都确定化。

//类模板
template<class T1,class T2>
class Temp
{
public:
	Temp()
	{
		cout << "template<class T1,class T2>" << endl;
	}
};

//全特化
template<>
class Temp<int, double>
{
public:
	Temp()
	{
		cout << "Temp<int, double>" << endl;
	}
};

2)偏特化

偏特化又分为两个部分,一是由如template<class T, int>的部分特化。

部分特化

template<class T1,class T2>
class Temp
{
public:
	Temp()
	{
		cout << "template<class T1,class T2>" << endl;
	}
};

template<class T1>
class Temp<T1,int>
{
public:
	Temp()
	{
		cout << "Temp<T1,int>" << endl;
	}
};

二是针对模板参数的特定条件限制所设计出来的特化版本,如对指针类型的特化。

template<class T1,class T2>
class Temp
{
public:
	Temp()
	{
		cout << "template<class T1,class T2>" << endl;
	}
};

//偏特化(特殊特化)
template<typename T1, typename T2>
class Temp<T1*, T2*>
{
public:
	Temp()
	{
		cout << "Temp<T1,int>" << endl;
	}
};

细节注意

函数模板或者类模板的定义与声明最好在一个文件中,将声明和定义放到一个文件 "xxx.hpp"或者”“xxx.h” ,否则会出现链接错误!


总结

最后对模板做个总结:

【优点】

1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生

2. 增强了代码的灵活性

【缺陷】

1. 模板会导致代码膨胀问题,也会导致编译时间变长

2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐