计算距对象起点的距离时,_ATL_PACKING 常量有什么用? [英] What's the use of _ATL_PACKING constant when computing distance from the start of object?
问题描述
ATL 具有 一组宏-称为COM映射.COM 映射是一个表,它将接口 GUID 与要添加到 this
指针以获取相应子对象的偏移量相关联 - 整个内容用作 显式 static_cast
用于 IUnknown::QueryInterface()
中的向上转换.
ATL features a set of macros for so-called COM maps. COM map is a table that associates an interface GUID with an offset that is to be added to this
pointer to get to the corresponding subobject - the whole stuff works as replacement to explicit static_cast
for the upcast inside IUnknown::QueryInterface()
.
地图条目是使用offsetofclass
宏构建的:
The map entries are built by using offsetofclass
macro:
#define _ATL_PACKING 8
#define offsetofclass(base, derived)
((DWORD_PTR)(static_cast<base*>((derived*)_ATL_PACKING))-_ATL_PACKING)
为了在这个问题中的可读性,我将其重写为以下伪代码函数":
which I'll rewrite as the following pseudocode "function" for readability in this question:
derived* derivedPointer = (derived*)_ATL_PACKING;
base* basePointer = static_cast<base*>(derivedPointer);
DWORD_PTR offset = (DWORD_PTR)(basePointer)-_ATL_PACKING;
看起来很合理 - 它获得一个指向虚构派生对象的指针,然后执行一个显式的 static_cast
来移动指针,然后计算这些虚构对象之间的距离.
Looks reasonable - it obtains a pointer to an imaginary derived object, then does an explicit static_cast
to shift the pointer, then computes distance between those imaginary objects.
问题是为什么这里有常数 8?为什么我们需要这个常数,为什么选择它是 8?
The question is why is the constant 8 there? Why do we need that constant and why is it chosen to be 8?
推荐答案
存在非零常量是因为宏不适用于空指针.我们知道空指针的值是一个空指针常量,其计算结果为 0
:
The non-zero constant is there because the macro does not work with null pointers. We know that the value of a null pointer is a null pointer constant which evaluates to 0
:
C++ 标准 4.10/1 指针转换 [conv.ptr]:
空指针常量是一个整数常量表达式 (5.19) 右值计算结果为零的整数类型.一种可以转换空指针常量指向指针类型;结果是该类型的空指针值是区别于其他所有值指向对象的指针或指向函数类型....
A null pointer constant is an integral constant expression (5.19) rvalue of integer type that evaluates to zero. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of pointer to object or pointer to function type....
这是关于从派生类转换为基类指针类型的相关子句:
This is the relevant clause with respect to converting from a derived class to a base class pointer type:
C++ 标准 4.10/3 指针转换 [conv.ptr]:
指向 cv D 的指针"类型的右值,其中 D 是一个类类型,可以是转换为右值类型指向 cv B 的指针",其中 B 是基数D 类(第 10 条).如果 B 是无法访问(第 11 条)或不明确(10.2) D 的基类,一个程序需要这种转换是畸形.的结果转换是指向基数的指针派生类的类子对象目的.空指针值为转换为空指针值目标类型.
An rvalue of type "pointer to cv D," where D is a class type, can be converted to an rvalue of type "pointer to cv B," where B is a base class (clause 10) of D. If B is an inaccessible (clause 11) or ambiguous (10.2) base class of D, a program that necessitates this conversion is ill-formed. The result of the conversion is a pointer to the base class sub-object of the derived class object. The null pointer value is converted to the null pointer value of the destination type.
在派生到基类的转换过程中,基本上空指针阻止了指针运算;你只会得到另一个空指针.该算术用于在此类转换期间修复"非空指针,以便它指向正确的子对象.offsetofclass
宏依赖于这个算法来确定偏移量.
Basically null pointers prevent pointer arithmetic from kicking in during a derived-to-base conversion; you will just get another null pointer. The arithmetic is used to "fix" non-null pointers during such conversions so that it points to the proper subobject. The offsetofclass
macro depends on this arithmetic to determine the offset.
8
使用的数字是任意的.您可以在那里使用任何数字,例如 1
或 4
,只要它不为零即可.
The number 8
used is arbitrary. You could've used any number there like 1
or 4
, as long as it wasn't zero.
这篇关于计算距对象起点的距离时,_ATL_PACKING 常量有什么用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!