Using static_cast is fine at the example but reinterpret_cast is not. Because reinterpret_cast is not convert vtable.
No, the problem is that the reinterpret_cast
is completely oblivious about the inheritance. It will simply return the same address unchanged1. But static_cast
knows that you're performing a downcast: i.e. casting from a base class to a derived class. Since it knows both types involved it adjusts the address accordingly, i.e., does the right thing.
Let's pretend our implementation lays out the hypothetical OVERLAPPEDEX
class that has a virtual function like this:
+------+------------+------------------+-------------+
| vptr | OVERLAPPED | AssociatedClient | ClientState |
+------+------------+------------------+-------------+
^
|
ptr
The pointer we're given points to the OVERLAPPED
subobject. reinterpret_cast
would not change that. It would only change the type. Obviously, accessing the OVERLAPPEDEX
class through this address would easily wreak havoc, because the locations of its subobjects are all wrong now!
what we believe we have when we access OVERLAPPEDEX through the pointer
+------+------------+------------------+-------------+
| vptr | OVERLAPPED | AssociatedClient | ClientState |
+------+------+-----+------+-----------+------+------+------+
| vptr | OVERLAPPED | AssociatedClient | ClientState | <- what we actually have
+------+------------+------------------+-------------+
^
|
ptr
static_cast
knows that to convert a OVERLAPPED*
to OVERLAPPEDEX*
it must adjust the address, and does the right thing:
+------+------------+------------------+-------------+
| vptr | OVERLAPPED | AssociatedClient | ClientState |
+------+------------+------------------+-------------+
^
|
ptr after static_cast
Though, if I use C-Style cast at there(not reinterpret_cast), could it also go wrong?
A C-style cast is defined as the first one of the following that succeeds:
const_cast
static_cast
static_cast
, then const_cast
reinterpret_cast
reinterpret_cast
, then const_cast
As you can see, a static_cast
is tried before reinterpret_cast
, so in this case, a C-style cast would also do the right thing.
More info
1Not guaranteed. There are very little guarantees about what happens on a reinterpret_cast
. All implementations I know of will simply give out the same address unchanged.
Best Answer
static_cast
provided that you know (by design of your program) that the thing pointed to really is anint
.static_cast is designed to reverse any implicit conversion. You converted to
void*
implicitly, therefore you can (and should) convert back withstatic_cast
if you know that you really are just reversing an earlier conversion.With that assumption, nothing is being reinterpreted -
void
is an incomplete type, meaning that it has no values, so at no point are you interpreting either a stored int value "as void" or a stored "void value" as int.void*
is just an ugly way of saying, "I don't know the type, but I'm going to pass the pointer on to someone else who does".reinterpret_cast
if you've omitted details that mean you might actually be reading memory using a type other than the type is was written with, and be aware that your code will have limited portability.By the way, there are not very many good reasons for using a
void*
pointer in this way in C++. C-style callback interfaces can often be replaced with either a template function (for anything that resembles the standard functionqsort
) or a virtual interface (for anything that resembles a registered listener). If your C++ code is using some C API then of course you don't have much choice.