***Template的“具现”行为***
template class中的任何member都只能通过template class的某个实体来存取或操作。
Point<float>::Status s; // ok
Point::Status s; // error
如果我们定义一个指针,指向特定的实体,像这样:
Point<float> *ptr = 0;
由于这是一个指向class object的指针,本身并不是一个class object,编译器不需要知道与该class有关的任何members数据。所以将“Point的一个float实体”具现也就没有必要。
如果不是一个pointer而是reference ,假设:
Point<float> &ref = 0;
这个定义的真正语意会被扩 展为:
// 内部扩展
Point<float> temp(float(0));
Point<float> &ref = temp;
以上转化是因为reference并不是无物(no object)的代名词,0被视作整数,必须被转换为类型Point<float>的一个对象。
然而, member functions只有在member functions被使用的时候,C++ Standard才要求它们被“具现 ”出来。这个规则的由来主要有两个原因:
(1)空间和效率的考虑。对于未使用的函数进 行“具现”将会花费大量的时间和空间;
(2)尚未实现的功能。并不是一个 template具现出来的所有类型一定能够完整支持一组member functions,因而只需具现真正需要的 member functions.
举个例子:
Point<float> *p = new Point<float>;
只有(a)Point template的float实例、(b)new 运算符、(c) default constructor需要被“具现”。
***Template的错误报告***
所有与类 型相关的检验,如果涉及到template参数,都必须延迟到真正的具现操作发生。
对于下面的 template声明:
template <class T>
class Mumble
{
public:
Mumble(T t = 1024) : _t(t)
{
if(tt != t)
throw ex ex;
}
private:
T tt;
}
其中像“T t = 1024”、“tt != t”这样的潜在错误在template声明时并不会报告,而会在每个具现操作发生时被检查出来并记录 之,其结果将因不同的实际类型而不同。
Mumble<int> mi; // 上述两个潜在错 误都不存在
Mumble<int*> pmi; // 由于不能将一个非零的整数常量指定给一个指针,故 “T t = 1024”错误