特化是什么? 模板参数在某种特定类型下的具体实现称为模板的特化
为什么要有特化? 因为编译器认为,对于特定的模板参数类型,如果你实现的更好,那就用你实现的
注意:模板的全特化和偏特化都是在已定义的模板基础之上,不能单独存在。
还是拿我们之前的顺序表举栗子:
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;
}
再次注意:模板的全特化和偏特化都是在已定义的模板基础之上,不能单独存在。
更多推荐
模板的全特化和偏特化
发布评论