C++Primer Plus 第十四章代码重用:14.4.4 数组模板示例和非类型参数2

14.4.4 数组模板示例和非类型参数

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


模板多功能性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章将讨论的标准模板库经常使用该特性,将默认类型设置为类。虽然可以为类模板类型参数提供默认值,但不能为函数模板参数提供默认值。然而,可以为非类型参数提供默认值,这对于类模板和函数模板都是适用的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值