ITEEDU

12.5 类模板与无类型参数

上节的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

性能提示12.2

如果可能,在编译时指定容器类(如数组类和堆栈类)的长度(可能通过非类型模板长度参数)可以消除用new动态生成空间的执行时开销。

软件工程视点12.3

如果可能,在编译时指定容器类的长度(可能通过非典型模板长度参数)以避免new无法取得所要内存时造成致命的造行时错误。

练习中要用无类型参数生成第8章开发的Array类的模板。这个模板可以用编译时指定类型的指定元素个数实例化Array对象,而不必在运行时动态生成Array对象的空间。

不符合常用类模板的特定类型的类可以重定义该类型的类模板。例如,可以用一个Array类模板实例化任何类型的数组。程序员可以控制某个类型Array类的实例化,如Martian,只要建立类名为Array<Martian>的新类即可。

12.6模板与继承

模板与继承关系如下所示:

●类模板可以从模板类派生。

●类模板可以从非模板类派生。

●模板类可以从类模板派生。

●非模板类可以从类模板中派生。

12.7 模板与友元

函数和整个类都可以声明为非模板类友元。使用类模板,可以声明各种各样的友元关系。友元可以在类模板与全局函数间、另一个类(可能是模板类)的成员函数间或整个类中(可能是模板类)建立。建立这种友元关系的符号可能很繁琐。

在下列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>的友元。

12.8 模板与static成员

在非模板类中,类的所有对象共享一个static数据成员,Static数据成员应在文件范围内初始化。

从类模板实例化的每个模板类有自己的类模板static数据成员,该模板类的所有对象共享一个Static数据成员。和非模板类的static数据成员一样,模板类的static数据成员也应在文件范围内初始化。每个模板类有自己的类摸板的static数据成员副本。