特化是什么? 模板参数在某种特定类型下的具体实现称为模板的特化

为什么要有特化? 因为编译器认为,对于特定的模板参数类型,如果你实现的更好,那就用你实现的

注意:模板的全特化和偏特化都是在已定义的模板基础之上,不能单独存在。

还是拿我们之前的顺序表举栗子:

template<class T>
class Vector
{
public:
	Vector();
	~Vector();
protected:
	size_t _size;
	size_t _capacity;
	T* _data;
};

template<class T>
Vector<T>::Vector() :_size(0), _capacity(3), _data(new T[_capacity])
{
	cout << "Vector<T>::Vector()" << endl;
}

template<class T>
Vector<T>::~Vector()
{
	delete[] _data;
	cout << "Vector<T>::~Vector()" << endl;
}

int main()
{
	Vector<int> v;
	return 0;
}

上面使用模板构建了一个顺序表,传参的时候必须显示的指定 Vector<int>类型

否则编译器会报错,会告诉我们类模板必须有模板参数列表,否则在开辟空间的时候不知道开多大的空间

全特化:全特化就是限定死模板实现的具体类型,

在以上的代码前提下,加这样一段代码,显示指定模板类型为int

template<>
class Vector<int>
{
public:
	Vector();
	~Vector();
protected:
	size_t _size;
	size_t _capacity;
	int* _data;
};

Vector<int>::Vector() :_size(0), _capacity(3), _data(new int[_capacity])
{
	cout << "Vector<int>::Vector()" << endl;
}

Vector<int>::~Vector()
{
	delete[] _data;
	cout << "Vector<int>::~Vector()" << endl;
}

当存在两份类的代码(当然第一份是创建对象以后才实例化出代码的),一种是普通模板,一种是全特化模板,这时候我们如果给模板传参Vector<int>,编译器会调用哪一份代码呢?

答案是显而易见的,当我们有全特化的模板类以后,定义出 一个 全特化类型 的 类对象时,首先调用的是全特化的代码

这就像是如果你家里已经有一碗下好的面条了(全特化),你就不会再去自己买面,再自己下了(普通类模板)...

如果我们要定义一个非全特化模板类型的对象,那他会调用谁呢?

以上代码说明,Vector<int> v1 调用的是全特化类,Vector<double> v2调用的是普通模板类,因为函数调用时使用的是调用栈,满足先进后出的特性,所以会先析构后创建的对象

偏特化(局部特化):偏特化就是如果这个模板有多个类型,那么只限定其中的一部分。

我们换一个多个模板参数的栗子:

template<class T1,class T2>
class Date
{
public:
	Date();
protected:
	T1 _t1;
	T2 _t2;
};

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

定义对象的时候必须显示实例化模板参数类型

int main()
{
	Date<int,int> d1;
	return 0;
}

我们只特化其中一个模板参数类型,如下:

template<class T1>
class Date<T1, int>
{
public:
	Date();
protected:
	T1 _t1;
	int _t2;
};

template<class T>
Date<T, int>::Date()
{
	cout << "Date<T, int>::Date()" << endl;
}

可以看到,我们在定义类成员函数的时候,只需要将没有被特化的模板参数

下面的定义对象的时候都调用哪一个代码呢?

int main()
{
	Date<float, int> d1;
	Date<char, int> d2;
	Date<double, int> d3;
	Date<string, int> d4;
	Date<int, int> d5;
	return 0;
}

我们可以观察到,只要第二个参数是int型,那么就会调用我们偏特化的模板类

但是只要第二个参数不为int,就会调用我们普通的模板类(d6)

局部特化两个参数为指针:

template<class T1,class T2>
class Date<T1*, T2*>
{
public:
	Date();
protected:
	T1* _pt1;
	T2* _pt2;
};


template<class T1,class T2>
Date<T1*, T2*>::Date()
{
	cout << "Date<T1*, T2*>::Date()" << endl;
}
	Date();
protected:
	T1* _pt1;
	T2* _pt2;
};


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

局部特化两个参数为引用:

template<class T1, class T2>
class Date<T1&, T2&>
{
public:
	Date(const T1& t1, const T2& t2);
protected:
	const T1& _t1;
	const T2& _t2;
};

template<class T1, class T2>
Date<T1&, T2&>::Date(const T1& t1, const T2& t2) :_t1(t1), _t2(t2)
{
	cout << "Date<T1&, T2&>::Date()" << endl;
}

再次注意:模板的全特化和偏特化都是在已定义的模板基础之上,不能单独存在。

更多推荐

模板的全特化和偏特化