Typically, when you cast an address to a type, you are simply changing how that address is being interpreted - that does not change the address. But in the case of C++, casting can actually change the address.
Say you have this hierarchy:
class C : public A, B
{
};
Then if you do this (not necessarily the recommended way, static_cast is better because it makes your intentions clearer and it is a bit safer):
C c;
A *a = (A *)&c;
Then, if the members of c started at 0xa34c0000 (on a 32-bit machine say), the physical contents of a will be the same i.e. (void *)a == (void *)&c.
But if you do this:
C c;
B *b = (B *)&c;
Then, if c started at 0xa34c0000, b will start at 1 beyond 0xa34c0000 + size of class A members.
That means, that say if A were a pure virtual class with only a vptr as a data member, B would start at 0xa34c0004. Thus the above cast would change the memory address in the result, and rightly so.
Probably something that is trivial for the experienced C++ programmer, but does trip you up when you are accustomed to casts not changing addresses on you - in C land, for example.
*PS: In the virtual base class example above a reinterpret cast would actually put 0xa34c0000 in b as well:
B *b = reinterpret_cast<B*>&c;
But that is disastrous because class B does not start at that address. In general, reinterpret_cast means you are telling the compiler that you know more about the underlying type then the compiler does. If you use a direct C-style cast, C++ first tries to do a static_cast, which is why it ends up doing the right thing - incrementing the address by 4.
No comments:
Post a Comment