Endereço do ponteiro C ++ para membro de dados de classe no Visual Studio

Estou lendo o livroDentro do modelo de objeto C ++. No livro há um exemplo 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

No código anterior, a impressão do endereço Derived :: v1 & Derived :: v2 será ambas0. No entanto, se imprimir o mesmo endereço através de uma variável:

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

Examinando o tamanho de & Derived :: v1 e p, obtenho 4 em ambos.

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

O endereço de Derived :: v1 será0, mas o endereço de Derived :: v2 será4. Eu não entendo porque o & Derived :: v2 se tornou4 quando atribuí-lo a uma variável.

Examine o código assembly, quando consultar diretamente o endereço de Derived :: v2, ele é convertido em um0; mas quando atribuí-lo a uma variável, ele é traduzido para um4.

Eu testei em VS2008 e VS2012, o resultado é o mesmo. Então, acho que deve haver algum motivo para a Microsoft escolher esse design.

E se você fizer assim:

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

Pelo visto& Derivado :: v2 não é0. Por que o compilador distingue esses dois casos?

Alguém pode por favor dizer que a coisa acontece por trás? Obrigado!

--Editar--

Para aqueles que pensam, o & Derived :: v1 não recebe um endereço válido. Você nunca fez isso?

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

questionAnswers(4)

yourAnswerToTheQuestion