隐式实例化 (仅限 C + +)
除非模板特殊化已显式实例化或显式特殊化,否则编译器仅在需要定义时才会为模板生成特殊化。 这称为 隐式实例化。
仅以 C++0x 开头。
当存在显式实例化声明时,编译器不需要为非类,非内联实体生成特殊化。
仅限 C++0x 的结束。
如果编译器必须实例化类模板特殊化并且已声明该模板,那么还必须定义该模板。
例如,如果您声明一个指向类的指针,那么不需要该类的定义,并且将不会隐式实例化该类。 以下示例演示编译器何时实例化模板类:
template<class T> class X {
public:
X* p;
void f();
void g();
};
X<int>* q;
X<int> r;
X<float>* s;
r.f();
s->g();编译器需要实例化以下类和函数:- 声明对象
r时的X<int> X<int>::f()成员函数调用r.f()X<float>和X<float>::g()在类成员访问函数调用s->g()
X<T>::f() 和 X<T>::g() 才能编译上述示例。 (编译器将在创建对象 r时使用类 X 的缺省构造函数。) 编译器不需要实例化以下定义:- 类
X(当声明了指针p时) - 声明指针
q时的X<int> - 声明指针
s时的X<float>
template<class T> class B { };
template<class T> class D : public B<T> { };
void g(D<double>* p, D<int>* q)
{
B<double>* r = p;
delete q;
}赋值 B<double>* r = p 将类型为 D<double>* 的 p 转换为类型 B<double>*; 编译器必须实例化 D<double>。 编译器在尝试删除 q时必须实例化 D<int> 。如果编译器隐式实例化包含静态成员的类模板,那么不会隐式实例化这些静态成员。 仅当编译器需要静态成员的定义时,编译器才会实例化静态成员。 每个实例化的类模板特殊化都有自己的静态成员副本。 以下示例对此进行了演示:
template<class T> class X {
public:
static T v;
};
template<class T> T X<T>::v = 0;
X<char*> a;
X<float> b;
X<float> c;对象 a 具有类型为 char*的静态成员变量 v 。 对象 b 具有类型为 float的静态变量 v 。 对象 b 和 c 共享单个静态数据成员 v。隐式实例化的模板位于定义该模板的同一名称空间中。
如果超负荷解析涉及函数模板或成员函数模板特殊化,那么编译器将隐式实例化该特殊化的声明。