8.7.3 使用有多个形参的类模板(1)
要在类模板中使用多个类型形参,只需简单地扩展刚才看到的使用单个形参的示例即可。可以在模板定义中的任何位置使用各个类型形参。例如,可以定义一个使用两个类型形参的类模板:
- template<class T1, class T2>
- class CExampleClass
- {
- // Class data members
- private:
- T1 m_Value1;
- T2 m_Value2;
- // Rest of the template definition...
- };
上面那两个类数据成员的类型取决于初始化类模板的对象时为形参提供的类型。可以显式实例化模板而无须定义任何对象。例如,在CSamples模板的定义后面可以编写如下语句:
- template class CSamples<Foo>;
这个语句显式实例化了Foo类型的CSamples,但它没有实例化任何对象。如果Foo没有实现模板所需要的所有成员函数,那么编译器在进行上述显式实例化时将生成一个错误消息,就好像在定义这种类型的对象那样生成错误消息。
类模板中形参的类型不受限制。还可以在类定义中使用一些需要以常量或常量表达式进行替换的形参。在前面的CSamples模板中,我们随意将数组m_Values定义成包含100个元素。然而,还可以让该模板的用户在实例化对象时选择数组的大小,方法是将该模板定义成如下形式:
- template <class T, size_t Size> class CSamples
- {
- private:
- T m_Values[Size]; // Array to store samples
- int m_Free; // Index of free location in m_Values
- public:
- // Constructor definition to accept an array of samples
- CSamples(const T values[], int count)
- {
- m_Free = count < Size count : Size; // Don't exceed the array
- for(int i = 0; i < m_Free; i++)
- m_Values[i] = values[i]; // Store count number of samples
- }
- // Constructor to accept a single sample
- CSamples(const T& value)
- {
- m_Values[0] = value; // Store the sample
- m_Free = 1; // Next is free
- }
- CSamples() : m_Free(0) {} // Default constructor
- // Function to add a sample
- int Add(const T& value)
- {
- int OK = m_Free < Size; // Indicates there is a free place
- if(OK)
- m_Values[m_Free++] = value; // OK true, so store the value
- return OK;
- }
- // Function to obtain maximum sample
- T Max() const
- {
- // Set first sample or 0 as maximum
- T theMax = m_Values[0];
- for(int i = 1; i < m_Free; i++) // Check all the samples
- if(m_Values[i] > theMax)
- theMax = m_Values[i]; // Store any larger sample
- return theMax;
- }
- };
创建对象时给Size提供的数值将代替整个模板定义中该形参的所有实例。现在,可以像下面这样声明前面示例中的CSamples对象:
- CSamples<CBox, 3> myBoxes(boxes, _countof(boxes)););
因为可以为Size形参提供任何常量表达式,所以还可以这样写:
- CSamples<CBox, _countof(boxes)> myBoxes(boxes, _countof(boxes)));
不过,该示例的这种模板用法不太好,原来的版本要灵活得多。使Size成为模板形参的结果是,那些存储相同类型的对象但Size形参值不同的模板实例是完全不同的类,而且不能混用。例如,CSamples<double, 10>类型的对象不能在包含CSamples<double, 20>类型对象的表达式中使用。