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章將討論的標準模板庫經常使用該特性,將默認類型設置為類。雖然可以為類模板類型參數提供默認值,但不能為函數模板參數提供默認值。然而,可以為非類型參數提供默認值,這對于類模板和函數模板都是適用的。