c++ - 计算距对象起点的距离时,_ATL_PACKING 常量有什么用?

标签 c++ com macros casting atl

ATL 功能 a set of macros for so-called COM maps . COM 映射是一个将接口(interface) GUID 与偏移量相关联的表,该偏移量将添加到 this 指针以获取相应的子对象 - 整个工作作为 explicit static_cast for the upcast inside IUnknown::QueryInterface() 的替代品。 .

映射条目是使用offsetofclass宏构建的:

#define _ATL_PACKING 8
#define offsetofclass(base, derived)\
    ((DWORD_PTR)(static_cast<base*>((derived*)_ATL_PACKING))-_ATL_PACKING)

为了这个问题的可读性,我将重写为以下伪代码“函数”:

derived* derivedPointer = (derived*)_ATL_PACKING;
base* basePointer = static_cast<base*>(derivedPointer);
DWORD_PTR offset = (DWORD_PTR)(basePointer)-_ATL_PACKING;

看起来很合理 - 它获得一个指向虚构派生对象的指针,然后执行显式 static_cast 来移动指针,然后计算这些虚构对象之间的距离。

问题是为什么常量 8 在那里?为什么我们需要这个常数,为什么选择它为 8?

最佳答案

存在非零常量是因为宏不适用于空指针。我们知道空指针的值是一个空指针常量,其计算结果为 0:

C++ Standard 4.10/1 Pointer conversions [conv.ptr]:

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....

这是关于从派生类转换为基类指针类型的相关子句:

C++ Standard 4.10/3 Pointer conversions [conv.ptr]:

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 宏依赖于此算法来确定偏移量。

使用的数字 8 是任意的。您可以在那里使用任何数字,例如 14,只要它不为零即可。

关于c++ - 计算距对象起点的距离时,_ATL_PACKING 常量有什么用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5014061/

相关文章:

php - 在 PHP 的 DLL(.net) 中运行函数 - 似乎没有任何效果

c# - 从进程中获取当前打开的 Word 文档

macros - 将大型 SAS 数据集拆分为较小的数据集

c++ - C vs C++ 在 VS2015 中使用 cl 编译器

c++ - 无法填充动态类模板数组

c++ - 如何使用概念专门化类型特征?

c++ - 我如何根据宏中的类型做出决定?

c++ - 如何定义和平滑 3D cv::Mat

c# - 有没有办法注册免激活EXE COM组件

loops - SAS-自动拆分库中的所有数据集时出错