When you cast pointers across the hierarchy, actual numerical pointer values might change. There's nothing wrong with the fact that it changes. There's noting wrong with such a cast. How the numerical pointer values change depend on the physical layout of the class. It is an implementation detail.
In your example, the 4 byte change in pointer value might easily be caused by the presence of virtual table pointer in the derived class.
The change in pointer value will not corrupt any member variables. The example in your original post does not show any "corrupted member variables" and in general your claim about some member variables getting "corrupted" doesn't make much sense. Please, when you make such claims, illustrate them with an example, so that people can understand what on Earth your are talking about.
Update:
The fact that base class subobjects might have non-zero offsets inside the derived classes immediately mean that in order to perform a proper cast from derived pointer type to base pointer type the compiler must know the source type and the destination type and the relationship between them. For example, if you do this
B* pb = /* whatever */;
A* pa = pb;
the compiler will know how to properly offset pointer pa
from pointer pb
. But of you do this
A* pa = (void *) pb;
the compiler will forget about the relationship between A
and B
, fail to perform the proper offset and produce the invalid value of pa
. The effect would be the same as in
A* pa = reinterpret_cast<A*>(pb);
If you do it this way, the result will be meaningless. So, just don't do it.
Of course, if you manually inspect the numerical value of pb
and find out that it is, say, 0x12345678
, and then do
A* pa = (A*) 0x12345678;
you will also get completely meaningless results, because the computer has no way to know that it has to perform the proper offset of the pointer.
This will produce an illusion of members of A
getting "corrupted", while in fact the only thing that is corrupted is your pointer. And you are the one who corrupted it.