C/C++编程:模板的具现行为

1060 篇文章 295 订阅

具现

具现(instantiations):表示程序将真正的类型和表达式绑定到模板相关形式参数上的操作。也叫做实例化

举个例子:

template<class Type>
Type min(const Type& t1, const Type &t2){}

调用:

min(1.0, 2.0);

然后程序就会将Type绑定为double并产生min()的一个程序实体(并适当的mangling),其中t1、t2的类型都是double

模板如何"具现"

对于类模板:

template<class Type>
class Point{
public:
	enum Status {unallocated, normalized};

	Point(Type x = 0.0, Type y = 0.0, Type z = 0.0);
	~Point();

	void* operator new(size_t);
	void operator delete(void *, size_t);
private:
	static Point<Type> *freeList;
	static int chunkSize;
	Type _x, _y, _z;
};

首先,当编译器看到类模板的声明时,它会做出什么反应?

  • 实际程序中,什么反应也没有
  • 也就是说,上面的static data members并不可用。nested enum或者其enumerators也一样

虽然enum Status、enumerators的真正类型在所有的Point具现中都一样,但它们每一个都只能通过Point类模板的某个实体来存取或者操作。因此,我们可以这样写:

Point<float>::Status s;

但不能这样写:

// error
Point::Status s;

即使两种类型抽象的来说是一样的(而且,最理想情况下,我们希望这个enum只有一个实体被产生出来,如果不是这样,我们可能会会想要把这个enum抽出到一个nontemplete base class中,以避免多次拷贝)

同样,不能这样写:

Point::freeList;
Point::chunkSize;

必须明确指明其类型,才能使用freeList和chunkSize

Point<float>::freeList;
Point<float>::chunkSize;

像上面这样使用static member,会使其一份实体于Point类的float具现在程序中产生关联。如果这样写:

// 另一个实体(instance)
Point<double>::freeList;

就会出现第二个freeList实体,与Point类的double具现产生关联。

如果我们定义一个指针,指向特定的实体,比如:

Point<float> *ptr = 0;

这一次,程序中什么也没有发生。为什么呢?因为一个指向类对象的指针,本身并不是一个类对象,编译器不需要直到与该类有关的任何成员的数据或者对象布局数据

如果定义的不是指针而是引用,又将如何?

const Point<float> & ref = 0;

它会具现出一个Point的float实体。这个定义的真正语意会被扩展为:

//内部扩展
Point<float> temporary(float (0));
const Point<float> & ref = temporary;

为什么呢?因为引用并不是no object的代名词。0被视为整数,必须被转换为如下类型的一个对象:

Point<float>

如果没有转换成功,那么这个定义就是错误的,编译通不过。

如果一个类对象的定义,不管是编译器隐式生成(上面的temporary)还是程序员像下面一样的显式定义:

const Point<float> origin;

都会导致类模板的具现,也就是说,float instantiation的真正对象布局被产生出来。回顾之前的模板声明:Point有三个nonstatic members,每一个类型都是Type。Type现在被绑定为float,所以origin的配置空间必须足够容纳三个float成员。

然后,对于那些未被使用过的memeber function不应该被“实体”化,只有在成员函数被使用的时候,C++保证才要求它们被具现出来。

比如,当:

Point<float> *p = new Point<float>

时,只有Point模板的float实例、new运算符、默认构造函数需要被具现。注意,虽然new运算符是这个类的一个implicitly static member,以至于它不能直接处理其中任何一个nonstatic members,但它还是一来真正的模板参数类型,因为它的第一个参值size_t表示类的大小。

这些函数在什么时候被"具现”出来呢?当前流行两种策略:

  • 在编译时候。那么函数将"具现"于origin和p存在的那个文件中
  • 在链接时候。那么函数将被一些辅助工具重新激活。函数模板实体可能被放在这个文件中、别的文件中,或者一个分离的存储位置上
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值