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
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++ 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....
This is the relevant clause with respect to converting from a derived class to a base class pointer 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.
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.
The number 8
used is arbitrary. You could've used any number there like 1
or 4
, as long as it wasn't zero.