14.4.4 数组模板示例和非类型参数
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 14.4.4 数组模板示例和非类型参数
- 模板多功能性14.4.5
- 1.递归使用模板
- 程序清单 14.18 twod.cpp
- 2.使用多个类型参数
- 程序清单 14.19pairs.cpp
模板多功能性14.4.5
可以将用于常规类的技术用于模板类。模板类可用作基类,也可用作组件类,还可用作其他模板的类型参数。例如,可以使用数组模板实现栈模板,也可以使用数组模板来构造数组–数组元素是基于栈模板的栈。即可以编写下面的代码:
template<typenameT>or<class T>
class Array
{
private:
T entry;
};
template <typename Type>
class GrowArray :public Array<Type>{...);// inheritance
template <typename Tp>
class Stack
{
//use an rray<>as a component
Array<Tp> ar;
...
};
Array <Stack<int>>asi;//an array of stacks of int
在最后一条语句中,C++98要求使用至少一个空白字符将两个>符号分开,以免与运算符>>混淆。C++11不要求这样做。
1.递归使用模板
另一个模板多功能性的例子是,可以递归使用模板。例如,对于前面的数组模板定义,可以这样使用它:
ArrayTP< ArrayTP<int,5>,10> twodee;
这使得twodee 是一个包含 10个元素的数组,其中每个元素都是一个包含5个 int 元素的数组。与之等价的常规数组声明如下:
int twodee[10][5];
请注意,在模板语法中,维的顺序与等价的二维数组相反。程序清单14.18使用了这种方法,同时使用 ArayTP模板创建了一维数组,来分别保存这10个组(每组包含5个数)的总数和平均值。方法调用cout.width(2)以两个字符的宽度显示下一个条目(如果整个数字的宽度不超过两个字符)。
程序清单 14.18 twod.cpp
// twod.cpp -- making a 2-d array
#include <iostream>
#include "arraytp.h"
int main(void)
{
using std::cout;
using std::endl;
ArrayTP<int, 10> sums;
ArrayTP<double, 10> aves;
ArrayTP< ArrayTP<int,5>, 10> twodee;
int i, j;
for (i = 0; i < 10; i++)
{
sums[i] = 0;
for (j = 0; j < 5; j++)
{
twodee[i][j] = (i + 1) * (j + 1);
sums[i] += twodee[i][j];
}
aves[i] = (double) sums[i] / 10;
}
for (i = 0; i < 10; i++)
{
for (j = 0; j < 5; j++)
{
cout.width(2);
cout << twodee[i][j] << ' ';
}
cout << ": sum = ";
cout.width(3);
cout << sums[i] << ", average = " << aves[i] << endl;
}
cout << "Done.\n";
// std::cin.get();
return 0;
}
下面是程序清单 14.18所示程序的输出。在twodee 的10个元素(每个元素又是一个包含5个元素的数组)中,每个元素对应于1行:列出了每个元素包含的值、这些值的总和以及平均值。
2.使用多个类型参数
模板可以包含多个类型参数。例如,假设希望类可以保存两种值,则可以创建并使用Pair 模板来保存两个不同的值(标准模板库提供了类似的模板,名为 pair)。程序清单 14.19 所示的小程序是一个这样的示例。其中,方法 first()const和second()const报告存储的值,由于这两个方法返回 Pair 数据成员的引用,因此让您能够通过赋值重新设置存储的值。
程序清单 14.19pairs.cpp
// pairs.cpp -- defining and using a Pair template
#include <iostream>
#include <string>
template <class T1, class T2>
class Pair
{
private:
T1 a;
T2 b;
public:
T1 & first();
T2 & second();
T1 first() const { return a; }
T2 second() const { return b; }
Pair(const T1 & aval, const T2 & bval) : a(aval), b(bval) { }
Pair() {}
};
template<class T1, class T2>
T1 & Pair<T1,T2>::first()
{
return a;
}
template<class T1, class T2>
T2 & Pair<T1,T2>::second()
{
return b;
}
int main()
{
using std::cout;
using std::endl;
using std::string;
Pair<string, int> ratings[4] =
{
Pair<string, int>("The Purpled Duck", 5),
Pair<string, int>("Jaquie's Frisco Al Fresco", 4),
Pair<string, int>("Cafe Souffle", 5),
Pair<string, int>("Bertie's Eats", 3)
};
int joints = sizeof(ratings) / sizeof (Pair<string, int>);
cout << "Rating:\t Eatery\n";
for (int i = 0; i < joints; i++)
cout << ratings[i].second() << ":\t "
<< ratings[i].first() << endl;
cout << "Oops! Revised rating:\n";
ratings[3].first() = "Bertie's Fab Eats";
ratings[3].second() = 6;
cout << ratings[3].second() << ":\t "
<< ratings[3].first() << endl;
// std::cin.get();
return 0;
}
对于程序清单 14.19,需要注意的一点是,在main()中必须使用 Pair<string,int>来调用构造函数,并将它作为 sizeof的参数。这是因为类名是Pair<string,int>,而不是Pair。另外,Pair<char *,double>是另一个完全不同的类的名称。
3.默认类型模板参数
类模板的另一项新特性是,可以为类型参数提供默认值:template <class Tl,class T2=int>class Topo…;这样,如果省略T2的值,编译器将使用int:
Topo<double,double>ml;//Tl is double,T2 is doubleTopo<double>m2;//Tl is double,T2 is int
第16章将讨论的标准模板库经常使用该特性,将默认类型设置为类。虽然可以为类模板类型参数提供默认值,但不能为函数模板参数提供默认值。然而,可以为非类型参数提供默认值,这对于类模板和函数模板都是适用的。