模板和STL 2

模板和STL 2
类模板{类模板的使用 静态成员与递归实例化 类模板的特化 类模板的局部特化 类模板参数的缺省值}
类模板的使用{类模板的两步实例化 调用实例化 类模板参数不支持隐式推断}
静态成员与递归实例化{类模板的静态成员 类模板的递归实例化}
类模板的特化 {全类特化 成员特化}
类模板的局部特化{对部分模板参数自行指定 同等程度地特化匹配导致歧义}
类模板参数的缺省值{类模板可以带有缺省参数 后面的参数可以引用前面参数}

类模板的定义
模板参数的语法形式
模板参数必须用如下形式的语法来声明
–template<typename 类型参数1,typename 类型参数2,…>
例如:
–template<typename A,typename b,typename _C>
class MyClass{
public:
A m_a;
b foo(_C c);
};

类型参数
在类模板的内部,类型参数可以像其他任何具体类型一样,用于成员变量,成员函数,成员类型(内部类型),甚至基类的声明
–template<typename M,typename R,typename A,typename V,typename T,typename B>
class MyClass:public B{
M m_mem;
R function(A arg){… V var …}
typename T* pointer;
};

类模板的使用
类模板的两步实例化
.从类模板到对象实际上经历了两个实例化过程
–编译器:编译器将类模板实例化为类并生成对象创建指令
–运行期:处理器执行对象创建指令将类实例化为内存对象

类模板本身并不代表一个确定的类型,既不能用于定义对象,也不能用于声明指针或引用。只有通过模板实参将其实例化为具体类以后,可具备类型语义
-类模板名<类型实参1,类型实参2,…>

调用谁实例化谁
类模板中,只有那些被调用的成员函数才会被实例化,即产生实例化代码。某些类型虽然并没有提供类模板所需要的全部功能,但照样可以实例化该类模板,只要不直接或间接调用那些依赖于未提供功能的成员函数即可;
–templateclass Comparator{
T const& max(void)const{
return m_x < m_y ? m_y:m_x;}
T const& min(void)const{
return m_x >m_y?m_y:m_x;}};
-class Integer{bool operator<(Integer const& rhs);}
-Comparatorci(123,456);
cout<< ci.max()<<endl;

类模板参数不支持隐式推断
与函数模板不同,类模板的模板参数不支持隐式推断
–template
class Comparator{
public:
Comparator(T const& x,T const& y):
m_x(x),m_y(y){}

private:
int m_x,m_y;}};
-Comparator ci(123,456);//错误
-Comparatorci(123,456);

静态成员与递归实例化
类模板的静态成员
类模板的静态成员变量,既不是一个对象一份,也不是一个模板一份,而是在该类模板的每个实例化类中,各有一份独立的拷贝,且为该类的所有实例化对象共享
–templateclass T{
public:
static void print(void){
cout<< &m_i <<’’<<&m_t<<endl;}
private:
static int m_i;
static T m_t;}p;
–templateint A::m_i;
templateT A::m_t;

.类模板的类型实参可以是任何类型,只要该类型能够提供模板所需要的功能
.模板自身的实例化类亦可实例化其自身,谓之递归实例化。通过这种方法可以很容易地构建那些在空间上具有递归特性的数据结构
–template
class array{
T m_array[3];
};
-Arraya1;//一维数组
Array<Array>a2;//二维数组
Array<Array<Array>>a3;//三维数组

类模板的特化
全类特化
.特化一个类模板可以特化该类模板的所有成员函数,相当于重新写一个针对某种特定类型的具体类
-template<>class Comparator<char const*>{
public:
Comparator(char const* const& x,char const* const& y):m_x(x),m_y(y){}
char const* const& max(void)const{return strcmp(m_x,m_y)<0?m_y:m_x;}
private:
char const* const& m_x,&m_y;
};
-Comparator<char const*>cmp(“hello”,“world”);
cout<<cmp.max()<<endl;//world

成员特化
.类模板除了可以整体进行特化以外,也可以只针对部分成员函数进行特化
-templateclass Comparator{
public:
Comparator(T const& x,T const& y):
m_x(x),m_y(y){}
T const& max(void)const{
return m_x<m_y?m_y:m_x;}
private:
T const& m_x,&m_y;};
-template<>char const* const& Comparator<
char const*> ::max(void)const{
return strcmp(m_x,m_y)<0?m_y:m_x;}

类模板的局部特化
对部分模板参数自行指定
.类模板可以被局部特化,即一方面为类模板指定特定的实现,另一方面又允许用户对部分模板参数自行指定
–//基本版本
template<typename A,typename B>class X{};
.//针对第二个模板参数取short的局部特化
templateclass X<A,short>{};
//针对两个模板参数取相同类型的局部特化
templateclass X<A,A>{};
//针对两个模板参数取某种类型引用的局部特化
template<typename A,typename B>class X<A* ,B*>{};
//针对两个模板参数取某种类型数组的局部特化
template<typename A,typename B>class X<A& ,B&>{};
//针对两个模板参数取某种类型数组的局部特化
template<typename A,typename B>class X<A[],B[]>{};

同等程度地特化匹配导致歧义
如果多个局部特化同等程度地匹配某个声明,那么该声明将因二义性而导致歧义错误
–X<int*,int*>x;//错误
.templateclass A<A,A>{};
.tempate<typename A,typename B>class X<A*,B*>{};
除非有更好的匹配
-X<int*,int*>x;
.templateclass X<A*,A*>{};

类模板参数的缺省值
类模板可以带有缺省参数
.类模板的模板参数可以带有缺省值,即缺省模板实参
–实例化类模板时,如果提供了模板实参则用所提供的模板实参实例化相应的模板形参,如果没有提供模板实参则相应的模板形参取缺省值
例如:
–templateclass X{…};
–X<char,short>x1(…);//X<char,short,string>x1(…)
Xx2(…);//X<char,double,string>X2(…)
X<>x3(…);//X<int,double,string>x3(…)
.如果类模板的某个模板参数带有缺省值,那么它后面的所有模板参数必须都带有缺省值;

后面的参数可以引用前面参数
.类模板后面参数的缺省值可以引用前面参数的值
–template<typename A,typename B=A*>
class X{…};
–Xx;//等价于X<int,int*>x
例如:
-template<typename T,typename C=vector>
class Stack{
public:
void push(T const& elem){
m_container.push_back(elem);}
private:
C m_container;};

非类型模板参数
非类型模板类型==》数值形式的模板参数{普通数值作为模板参数;非类型模板参数只能是常量}

数值形式的模板参数
普通数值作为模板参数
模板的参数并不局限于类型参数,普通数值也可以作为模板的参数,前面不要写typename,而要写具体类型
–typename<typename T,size_t C>class Array{
public:
T& operator[](size_t i){
return m_array[i];}
T const& operator[](size_t i)const{
return const_cast<Array&>(*this)[i];}
size_t capacity(void)const{return C;}
private:
T m_array[C];};
–Array<int,10>array;
for(int i=0;i<array.capacity();++i)array[i]=i+1;

非类型模板参数只能是常量
非类型模板参数只能是常量、常量表达式,以及带有常属性(const)的变量,但不能同时具有挥发性(volatile)
–Array<int,10>array;
–Array<int,3+7>array;
-int const x=3,y=7;
Array<int,x+y>array;
-int const volatile x=3,y=7;
Array<int,x+y>array;//错误

发布了21 篇原创文章 · 获赞 16 · 访问量 3766

猜你喜欢

转载自blog.csdn.net/qq_40632341/article/details/104140653