Dirección del puntero de C ++ al miembro de datos de clase en Visual Studio

Estoy leyendo el libroDentro del modelo de objetos C ++. En el libro hay un ejemplo como:

struct Base1
{
    int v1;
};

struct Base2
{
    int v2;
};

class Derived : public Base1, public Base2 {};

printf("&Derived::v1 = %p\n", &Derived::v1);        // Print 0 in VS2008/VS2012
printf("&Derived::v2 = %p\n", &Derived::v2);        // Print 0 in VS2008/VS2012

En el código anterior, la impresión de la dirección Derived :: v1 & Derived :: v2 será0. Sin embargo, si imprime la misma dirección a través de una variable:

int Derived::*p;
p = &Derived::v1;
printf("p = %p (&Derived::v1)\n", p);        // Print 0 in VS2008/VS2012 as before
p = &Derived::v2;
printf("p = %p (&Derived::v2)\n", p);        // Print 4 in VS2008/VS2012

Al examinar el tamaño de & Derived :: v1 y p, obtengo 4 en ambos.

// Both are 4
printf("Size of (&Derived::v1) is %d\n", sizeof(&Derived::v1));
printf("Size of p is %d\n", sizeof(p));

La dirección de Derived :: v1 será0, pero la dirección de Derived :: v2 será4. No entiendo por qué & Derived :: v2 se convirtió4 cuando se lo asigna a una variable.

Examine el código de ensamblaje, cuando consulte directamente la dirección de Derived :: v2, se traducirá a un0; pero cuando se lo asigna a una variable, se traduce a una variable.4.

Lo probé tanto en el VS2008 como en el VS2012, el resultado es el mismo. Así que creo que debe haber alguna razón para que Microsoft elija tal diseño.

Y, si te gusta esto:

d1.*(&Derived::v2) = 1;

Aparentemente& Derivado :: v2 no es0. ¿Por qué el compilador distingue estos dos casos?

¿Alguien puede por favor decir que la cosa pasa detrás? ¡Gracias!

--Editar--

Para aquellos que piensan que & Derived :: v1 no obtiene una dirección válida. ¿Nunca has hecho esto?

Derived d1, d2;
d1.*p = 1;
d2.*p = 1;

Respuestas a la pregunta(4)

Su respuesta a la pregunta