C++Primer Plus 第十四章代码重用
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:C++Primer Plus 第十四章代码重用:14.4.7 成员模板
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- C++Primer Plus 第十四章代码重用
- 前言
- 14.4.7 成员模板
- 14.4.7 成员模板
前言
提示:这里可以添加本文要记录的大概内容:
14.4.7 成员模板
提示:以下是本篇文章正文内容,下面案例可供参考
14.4.7 成员模板
模板可用作结构、类或模板类的成员。要完全实现STL的设计,必须使用这项特性。程序清单14.20是一个简短的模板类示例,该模板类将另一个模板类和模板函数作为其成员。
程序清单14.20 tempmemb.cpp
//tempmemb.cpp -- template members
#include <iostream>
using std::cout;
using std::endl;
template <typename T>
class beta
{
private:
template<typename V> // nested template class member
class hold
{
private:
V val;
public:
hold(V v) : val(v) {}
void show() const { cout << val << endl; }
V Value() const { return val; }
};
hold<T> q; //template object
hold<int> n; //template object
public:
beta(T t, int i) : q(t), n(i) {}
template<typename U>
U blab(U u, T t) { return n.Value() + q.Value() * u / t; };
void show() const { q.show(); n.show(); }
};
int main()
{
beta<double> guy(3.5, 3);
cout << "T was set to double.\n";
guy.show();
cout << "V was set T,which is double,then V was set to int\n";
cout << guy.blab(10, 2.3) << endl;
cout << "U was set to int.\n";
cout << guy.blab(10.0, 2.3) << endl;
cout << "U was set to double.\n";
return 0;
}
在程序清单 14.20中,hold 模板是在私有部分声明的,因此只能在 beta 类中访问它。beta 类使用 hold模板声明了两个数据成员:
hold<T>q;
hold<int>n;
n是基于 int 类型的 hold 对象,而q成员是基于T类型(beta模板参数)的 hold 对象。在 main()中,下述声明使得T表示的是 double,因此q的类型为hold:
beta<double>guy(3.5,3);
blab()方法的U类型由该方法被调用时的参数值显式确定,T类型由对象的实例化类型确定。在这个例子中,guy的声明将T的类型设置为 double,而下述方法调用的第一个参数将U的类型设置为int(参数10对应的类型):
cout << guy.blab(10,2.5)<< endl;
因此,虽然混合类型引起的自动类型转换导致 bab()中的计算以 double 类型进行,但返回值的类型为U(即 int),因此它被截断为28,如下面的程序输出所示:
注意到调用 guy.blab()时,使用10.0代替了10,因此U被设置为 double,这使得返回类型为 double,
因此输出为 28.2608。正如前面指出的,guy 对象的声明将第二个参数的类型设置为double。与第一个参数不同的是,第二个参数的类型不是由函数调用设置的。例如,下面的语句仍将blah()实现为blah(int,double),并根据常规函数原型规则将3转换为类型double:
cout << guy.blab(10,3)<< endl;
可以在 beta 模板中声明 hold 类和 blah 方法,并在 beta 模板的外面定义它们。然而,很老的编译器根本不接受模板成员,而另一些编译器接受模板成员(如程序清单 14.20所示),但不接受类外面的定义。然而,如果所用的编译器接受类外面的定义,则在 beta模板之外定义模板方法的代码如下:
上述定义将T、V和U用作模板参数。因为模板是嵌套的,因此必须使用下面的语法:
template <typename T>
template <typename V>
而不能使用下面的语法:
template<typename T,typename V>
定义还必须指出 hold 和 blab 是 beta类的成员,这是通过使用作用域解析运算符来完成的。