《c++ templates》学习笔记(2)——第三章

 

1       类模板

1.1    类模板的声明

类模板的定义和实现都被放在头文件中,这点和函数模板类似。

Template<typename T>

Class Stack{

Private:

       Std::vector<T> elems;

Public:

       Stack();

       Void push(T const&);

       Void pop();

      

};

这个类的类型是Stack<T>,其中T是模板参数。所以,如果你要声明自己实现的拷贝构造函数和赋值运算符,那么应该这样写:

Template<typename T>

Class Stack{

Public:

       Stack(Stack<T> const&);

       Stack<T>& operator=(stack<T> const&);

};

当然,使用类名而不是类的类型时,就应该只使用stack,譬如,当你指定类的名称、类的构造函数、析构函数,就应该用Stack

 

1.2    成员函数的实现

为了定义类模板的成员函数,你必须指定该成员函数是一个函数模板,而其你还需要使用这个类模板完整类型限定符。因此,类型Stack<T>的成员函数push()的实现如下。

Template<typename T>

Void Stack<T>::push(T const& elem)

{

       Elems.push_back (elem);

}

对于类模板的任何成员函数,你都可以把它实现为内联函数,将它实现于类的声明里面。

 

1.3    类模板的使用

为了使用类模板,你必须显示的指定模板实参,类模板不会进行实参演绎,这点和函数模板有所不同。

 

只有那些被调用的成员函数,才会产生这些函数的实例化代码。对于类模板,成员函数只有在被使用的时候才会被实例化。显然,这样可以节省空间和时间;另一个好处是对于那些“未能提供所有成员函数中所有操作”的类型,你也可以使用该类型来实例化类模板,只要对那些“未能提供某些操作的”成员函数,模板内部不使用就可以了。

 

如果类模板中含有静态成员,那么用来实例化的每种类型,都会实例化这个静态成员。

 

如果用类模板来作为模板参数时,要注意尖括号的位置。

Stack<stack<int> > intStackStack;

 

1.4    类模板的特化

和函数模板的重载类似,通过特化类模板,你可以优化基于某种特定类型的实现,或者克服某种特定类型在实例化类模板时所出现的不足。另外,如果要特化一个类模板,你还要特化该类模板的所有成员函数,虽然也可以只特化某个成员函数,但这个做法并没有特化整个类,也就没有特化整个类模板。

特化的语法:

Template<>

Class Stack<std::string>{

      

};

在进行类模板的特化时,每个成员函数都必须重新定义为普通函数,原来模板函数中的每个T也相应的被进行特化的类型取代。

如:

Void Stack<std::string>::push (std::string const& elem)

{

       Elems.push_back(elem);

}

注意到,在函数定义的前面,没有template<std::string>

 

特化的实现可以和基本类模板的实现完全不同。

 

1.5    局部特化

类模板可以被局部特化,你可以在特定的环境下指定类模板的特定实现,并且要求某些模板参数仍然必须有用户来定义。

如:

Template<typename T1, typename T2>

Class MyClass{…};

可以被特化为:

Template<typename T, typename T>

Class MyClass<T, T>{…};

 

Template<typename T>

Class MyClass<T, int>{…};

 

Template<typename T1, typename T2>

Class MyClass<T1*, T2*>{…};

 

1.6    缺省模板实参

和函数模板不同,类模板的实参允许有缺省值。

比如对于上面定义的Stack,就可以有下面的实现。

Template<typename T, typename CONT= std::vector<T> >

Class Stack{

      

};

 

原文地址:https://www.cnblogs.com/strinkbug/p/1334677.html