Topic: downcasting problem


Author: kriss@cao-vlsi.ibp.fr (Christophe GROSJEAN)
Date: 1995/06/27
Raw View
Consider the following :

class Base
{
 // some stuff
};

class Derived : public Base, public OtherBase
{
 // some stuff
};

Derived * dp;

is it always true that :

 ((Derived *)((Base *)dp)) == dp

I need this for some code of mine to work
(I can ensure Base is the first Base class
and that I don't need virtual inheritance)
It seems to be OK for all the compilers I tried
but I couldn't find anything positive about this
in the draft.

Thanks for advices.





Author: kriss@cao-vlsi.ibp.fr (Christophe GROSJEAN)
Date: 1995/06/27
Raw View
I put something wrong in my previous question :

what I must ensure is

 &*((Derived *)((Base *)dp)) == &*dp == &*(void*)dp

(that I get the same address wathever the casting,
in fact my problem is an allocation problem when loading objects
from a text file. but the crucial point is above)
My first statement was obviously true.





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/06/27
Raw View
In article 95Jun27160813@cao-vlsi.ibp.fr, kriss@cao-vlsi.ibp.fr (Christophe GROSJEAN) writes:
>
>I put something wrong in my previous question :
>
>what I must ensure is
>
> &*((Derived *)((Base *)dp)) == &*dp == &*(void*)dp
>
>(that I get the same address wathever the casting,
>in fact my problem is an allocation problem when loading objects
>from a text file. but the crucial point is above)
>My first statement was obviously true.

The first equality is always true as long as all the class definitions
are visible at that point. That is, casting pointers among classes in
a hierarchy may involve adjustment to the addresses, so the compiler
must know exactly what the relationship is. ("Always true" because
in this example the downcast is unambiguous.)

If you have static_cast and dynamic_cast available, they are safer
ways to do the casting; you get compiler help if you omit a needed
declaration or mistype something. dynamic_cast also allows you to
downcast from a virtual base class, something otherwise not possible.

The second equality has two problems. First, you are dereferencing
a void*, the results of which are undefined.

Next, you are comparing a void* with a Derived*. When these are compared,
the compiler casts the Derived* to a void* and then does the comparison.
My point is you have to be careful about inserting casts to void*,
because it throws away all type information. For example, the result of
 (Base*)dp == (void*)dp
could be either true or false, depending on the details of the hierarchy
and class layout. The left side is cast to Base*, which might adjust the
pointer value, then implicitly to void* to make the comparison. The right
side just casts the original pointer value to void*.

Perhaps you were asking if you can count on the address of a base class
being the same as the address of the complete object. The answer is "no",
not even for single inheritance with no virtual base classes. The C++
implementor is allowed considerable freedom in laying out classes. For
example, there is no rule against laying out a class with the derived
portion following, instead of preceding, the base portion.

When you use correctly-typed pointers, the compiler makes any needed
address adjustments implicitly when pointers are converted to other types.
You should not make any assumptions about class layout in portable code.

---
Steve Clamage, stephen.clamage@eng.sun.com