* "Jacob Jensen said:
* Alf said:
reinterpret_cast is just a way of telling the compiler to regard the bits
as having some other type than the original, and that's dangerous. The
bits may not even be meaningful when regarded as a value of the new type.
So you have essentially no well-defined operations on the result, other than
casting it back to the original type.
Is it because a pointer to a type A may have a different byte [you mean bit]
representation that a pointer to a type B?
It may in general, yes.
The standard lays out the rules in §5.2.10, with slightly different details
for different pointer types (pointer to function, to object, to member function),
but in general the only well-defined operation is to reinterpret_cast back to
the original type, in which case you get the original value back.
Exception: reinterpret_cast of null-pointer yields a valid null-pointer.
In your specific example I can't see any way the bits could be different,
but the standard is conservative: you can't use the result of a
reinterpret_cast for anything other than casting it back -- unless you
use knowledge of a particular compiler and system.
An example where it's obvious that different bit-level values must be
involved is when you have
class A{ ... };
class Middle1: public A { ... };
class Middle2: public A { ... };
class B: public Middle1, public Middle2 { ... };
Here a B object contains two different A subobjects. Casting using
static_cast from B* to Middle1* to A* gets you a pointer to one of them,
casting using static_cast from B* to Middle2* to A* gets you a pointer to
the other, and these two pointers can't very well be the same bit pattern,
for if they were then they would refer to the same A subobject.
In above paragraph I use 'casting' and 'static_cast' even though no actual
cast notation need be involved, since it's pure upcasting. But without
cast notation what you get _is_ a static_cast. It goes like:
#include <iostream>
struct A{ int ahum; };
struct Middle1: A { int m1; };
struct Middle2: A { int m2; };
struct B: Middle1, Middle2 { int bah; };
int main()
{
B object;
B* b = &object;
Middle1* m1 = b;
Middle2* m2 = b;
A* a1 = m1;
A* a2 = m2;
std::cout
<< a1 << "\n" // Some pointer value.
<< a2 << "\n" // Some different pointer value.
<< std::flush;
// Try to go directly from an A subobject to the B object.
// Not accepted, the compiler doesn't know _which_ A subobject.
// Not knowing where the pointer points it can't adjust it.
//
// B* bummer = static_cast<B*>( a1 ); // Nope.
// Go via the relevant subobject that _you_ know.
B* better = static_cast<B*>( static_cast<Middle2*>( a2 ) );
std::cout
<< b << "\n" // Some pointer value.
<< better << "\n" // The same pointer value.
<< std::flush;
}
But as you say, I will have "no well-defined operations on the result, other
than casting it back to the original type".
But is that not what I am doing? I am casting it back to the type it
originally was/is.
In your particular case: yes in practice no in standard. In general just no.
The reason is that the innocent upcasts are static_cast's, which in general
may change the pointer value (bitpattern).
A bitpattern-preserving (and not even that much is guaranteed!) reinterpret_cast
is then not guaranteed to get back the original value.
So if that is correct, then please tell me why I should not use it instead
of using static_cast (Note: Only tell me if my statement of casting it to
its original type is the correct)?
OK.
And when do I use reinterpret_cast then?
Only in very low-level, platform-specific code.
Do I understand you correctly concerning the dynamic_cast thingy: There are
some cases when I do not know what type of pointer I have. And in that case,
I can try to cast it, and see if it gives a NULL pointer. That is my code
MUST handle the case where the cast is not valid. Am I right?
Yep. Except as John Harrison noted, if you're casting to reference instead
of to pointer what you get as ungood-signal is an exception, not NULL. With
casting to pointer you get NULL.
method.)
I would be interested in seeing a simple example of this. I need the above
downcast, because I have some API functions which I have to use that only
take the base class pointer as argument. So I have to upcast my pointer to
call the function ( func1() ), and then downcast it in a function that is
called by func1(), which is a function I have defined.
Off the cuff,
struct A{ virtual void something(){} };
struct B{ virtual void something(){ ... B stuff ... } };
void calledFunc( A* pObj ){ pObj->something(); } // Does B stuff.
void func1( A* pObj ){ calledFunc( pObj ); }
int main()
{
B obj;
func1( &obj );
}
(Actually the best explanation I know of for virtual functions is as a
solution to avoid downcasts in e.g. an arithmetic expression evaluator.
But that's a digression. It's a shame that example isn't wider known.)
If the above doesn't seem possible there are more advanced versions of the
same basic idea -- look up the "visitor pattern".
And if that doesn't seem possible perhaps some redesign can do the trick.
In general you should never need downcasts except when taking objects out
of polymorphic containers (that is, containers containing a bunch of
objects of different but related types).
Do you mean that all standard C++ compilers should have RTTI set?
Yes.
All C++ compilers must support RTTI and compile RTTI-based code
correctly, since RTTI is part of the language defined by the standard.
Without RTTI (or exceptions, or 'main' ;-) ) you have only a subset of C++.