ATL的特点是a set of macros for so-called COM maps。COM映射是一个表,它将接口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?
发布于 2011-02-16 18:12:37
之所以存在非零常量,是因为宏不能与空指针一起使用。我们知道null指针的值是一个null指针常量,其计算结果为0
C++标准4.10/1指针转换conv.ptr
空指针常量是整数类型的整数常量表达式(5.19) rvalue,其计算结果为零。null指针常量可以转换为指针类型;结果是该类型的null指针值,并且可以与指向对象的指针或指向函数类型的指针的其他值区分开来。
这是关于从派生类转换为基类指针类型的相关子句:
C++标准4.10/3指针转换conv.ptr
“指向cv的指针”类型的右值,其中D是类类型,可以被转换成“指向cv的指针”类型的右值,其中B是D的基类(第10条)。如果B是D的不可访问的(第11条)或不明确的(10.2)基类,则需要该转换的程序是病态的。转换的结果是指向派生类对象的基类子对象的指针。将空指针值转换为目标类型的空指针值。
基本上,空指针可以防止指针算法在从派生到基的转换过程中发挥作用;你只会得到另一个空指针。该算法用于在此类转换过程中“修复”非空指针,以便它指向正确的子对象。offsetofclass宏根据此算法来确定偏移量。
8使用的数量是任意的。您可以在那里使用任何数字,如1或4,只要它不是零。
https://stackoverflow.com/questions/5014061
复制相似问题