类型参数
泛型名称声明:
template<typename T>
上述T是一泛型名称,也是通过typename指明的类型参数,string,int作为具体的类型传入进去,非类型参数就是在模板中加入常规类型变量int n,n本身指的就是int型,不是用作泛型,就是非类型参数.
可设定大小容器类实现
模板通常用于容器类,容器类的大小可以自我设定有两种方法:
-
通过动态分配和构造函数参数,但是,这样比较麻烦,因为,在类中进行动态分配,要考虑到赋值运算符,复制构造函数的重写.
-
通过在模板上的参数添加非类型参数,指明数组大小,这样就更加方便,不用重写很多函数了
重新用非类型参数和数组完成一个简单类设计
template <typename T, int n>
class ArrayTP
{
private:
T ar[n]; // T为类型参数,n为非类型参数
public:
ArrayTP() {};
explicit ArrayTP(const T & v); // 防止T类型隐式转换
virtual T & operator[](int i); // 可以被赋值并改变数组中某个值的方法,用作左值
virtual T operator[](int i) const; // const不允许改变,而是返回一个值的副本,可以拿来进行赋值.
};
template <class T, int n>
ArrayTP<T,n>::ArrayTP(const T & v)
{
for (int i = 0; i < n; i++)
ar[i] = v;
}
template <class T, int n>
T & ArrayTP<T,n>::operator[](int i)
{
if (i < 0 || i >= n)
{
std::cerr << "Error in array limits: " << i
<< " is out of range\n";
std::exit(EXIT_FAILURE);
}
return ar[i];
}
template <class T, int n>
T ArrayTP<T,n>::operator[](int i) const
{
if (i < 0 || i >= n)
{
std::cerr << "Error in array limits: " << i
<< " is out of range\n";
std::exit(EXIT_FAILURE);
}
return ar[i];
}
非类型参数的限制:整形,枚举,引用,指针.所以double m是不合法的.上面的模板中,n不能能进行改变,所以n++和&n的等表达式不能用.而且非类型参数必须使用常量.
- 递归使用模板
模板可以自己作为一个类型参数调入.
ArratTP< ArrayTP<int , 5>,10 > twodee;
这句话的意思就是,twodee是一个的模板类的对象,存储十个元素,每个元素又是一个ArrayTP<int,5>类型的对象,ArrayTP<int ,5>对象存储的又是5个int型的整形,所以这个相当于二维数组的int twodee[10][5].
测试函数如下:
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";
return 0;
}
测试结果如下:
- 模板还可以用多个类型参数,比如template <typename T1,typename T2>.
有的时候希望类可以保存两种值,设计如下:
template <typename T1, typename 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;
}
测试函数如下:
i
nt 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;
return 0;
}
测试结果如下: