上节的Sstack类模扳只用模板首部的类型参数,也可以使用无类型参数(non-type parameter),无类型参数可以有默认参数,一般将无类型参数当作Const处理。例如,模板首都可以取int elements参数,如下所示:
template<class T,int elements> // note non-type parameter然后下列声明:
Stack<double,100) mostRecentSalesFigures;
实例化(在编译时)100个元素的Stack模板类mostRecentSalesFigures(使用double值)。这个模板类的类型为Stack<double,100>。类的首部可以包含private数据成员,数组声明如下:
T stackHolder[elements]; // array tO hold stack contents
如果可能,在编译时指定容器类(如数组类和堆栈类)的长度(可能通过非类型模板长度参数)可以消除用new动态生成空间的执行时开销。
如果可能,在编译时指定容器类的长度(可能通过非典型模板长度参数)以避免new无法取得所要内存时造成致命的造行时错误。
练习中要用无类型参数生成第8章开发的Array类的模板。这个模板可以用编译时指定类型的指定元素个数实例化Array对象,而不必在运行时动态生成Array对象的空间。
不符合常用类模板的特定类型的类可以重定义该类型的类模板。例如,可以用一个Array类模板实例化任何类型的数组。程序员可以控制某个类型Array类的实例化,如Martian,只要建立类名为Array<Martian>的新类即可。
模板与继承关系如下所示:
●类模板可以从模板类派生。
●类模板可以从非模板类派生。
●模板类可以从类模板派生。
●非模板类可以从类模板中派生。
函数和整个类都可以声明为非模板类友元。使用类模板,可以声明各种各样的友元关系。友元可以在类模板与全局函数间、另一个类(可能是模板类)的成员函数间或整个类中(可能是模板类)建立。建立这种友元关系的符号可能很繁琐。
在下列X类的类模板中声明为:
template<class T>class X
下列友元声明:
friend void f1();
使函数f1成为从上述类模板实例化的每个模板类的友元。
在下列X类的类模板中声明为:
template<class T>class X
下列友元声明:
friend void f2(X< T > 6);
对特定类型T(如float)使函数f2(X<float>&)成为X<float>的友元。
在类模板中,可以声明另一个类的成员函数是类模板产生的任何模板类的友元。只要用类名和二元作用域运算符指定其它类的成员函数名。例如,在下列X类的类模板中声明为:
template<class T>class X
下列友元声明:
friend void A::f4();
使A类的成员函数f4成为上述类模板实例化的任何模板类的友元。
在下列X类的类模板中声明为:
template<class T>class X
下列友元声明:
friend void C< T >::f5( X< T > & );
对特定类型T(如float)使成员函数:
C<float>::f5( X< float> & );
成为X<float>模板类的友元函数。
在下列X类的类模板中声明为:
template<Class T>Class X
可以声明第二个类Y,如下所示:
friend class Y;
使Y类的每个成员函数成为X的类模板产生的每个模板类的友元。
在下列X类的类模板中声明为:
template<class T>class X
可以声明第二个类Z,如下所示:
friend class Z< T >;
使模板类用特定类型T(如float)实例化时,class Z<float>的所有成员成为模板类X<float>的友元。
在非模板类中,类的所有对象共享一个static数据成员,Static数据成员应在文件范围内初始化。
从类模板实例化的每个模板类有自己的类模板static数据成员,该模板类的所有对象共享一个Static数据成员。和非模板类的static数据成员一样,模板类的static数据成员也应在文件范围内初始化。每个模板类有自己的类摸板的static数据成员副本。