Re: some casting questions
On Jun 17, 5:48 am, Jess <w...@hotmail.com> wrote:
On Jun 17, 4:30 am, James Kanze <james.ka...@gmail.com> wrote:
On Jun 16, 3:22 pm, Jess <w...@hotmail.com> wrote:
It seems both static_cast and dynamic_cast can cast a base class
pointer/reference to a derived class pointer/reference. If so, is
there any difference between them?
Several. The dynamic_cast does actual run-time type checking.
It will fail (return a null pointer or throw an exception) if
the actual object is not of the right type. In addition,
dynamic_cast can do many casts that aren't possible with
static_cast; roughly speaking, static_cast can only move up and
down in the inheritance lattice; dynamic_cast can move anywhere.
Thanks! Where else could dynamic_cast move to? Do you mean it cast an
object to a completely unrelated class object?
Not to a completely unrelated class, but consider something
like:
VB
/ \
L R
\ /
MD
The legal static_casts here are MD->L, MD->R, MD->VB, L->MB, and
R->MD. You'll notice that they all go up and down. All 12 of
the possible casts in the hierarchy are legal for dynamic_cast,
including such things as L->R.
Also, static_cast won't work from base to derived if the
inheritance is virtual.
What is "virtual" inheritance? Is it the same as having virtual
functions in a base class?
No. The two use the same keyword, but that's about it.
Basically, for a base class B (like VB above), all of the
instances inherited virtually are shared; there is just one
instance. For example, the above hierarchy would be created by
something like:
class VB {} ;
class L : public virtual VB {} ;
class R : public virtual VB {} ;
class MD : public L, public R {} ;
In other words, because both L and R inherit virtually from VB,
they both share the same instance.
Finally, dynamic_cast only works from
base to derived if the types are polymorphic; static_cast
doesn't have this restriction.
What types are polymorphic? Are they the ones with virtual
functions?
A type is polymorphic if and only if it is a class type with one
or more vitual functions, yes. It's the definition in the
standard.
If I have two classes, A is the base class, B is A's
derived class, then if A has virtual functions, then both A and B are
polymorphic?
Yes. Virtualness is inherited.
Therefore, does it mean I can dynamic_cast from A to B
and B to A only if they have virtual functions?
You can dynamic_cast from derived to base with or without
virtual functions. You can dynamic_cast from base to derived,
or elsewhere in the hierarchy, only from the point at which
there are virtual functions.
In general, when casting within an inheritance hierarchy, you'll
almost always want dynamic_cast. static_cast is generally only
used to or from void*, or with various scalar or class types
Can you please elaborate? :)
What is there to elaborate? Within an inheritance lattice,
practically, dynamic_cast covers all your needs. The base class
will have virtual functions, otherwise there is no point in
having a hierarchy, and dynamic_cast works everywhere. (Note
that if the base class doesn't have at least a virtual
destructor, you don't want pointers to it roaming about anyway.)
In some cases, you need to cast to and from void*, typically in
the case of C compatible callbacks. In such cases, you may
prefer static_cast, because there are no virtual functions. If
there are virtual functions, the problem is a bit more
complicated---you must 1) cast the pointer to the final type
(typically a base class), using either static_cast or
dynamic_cast, 2) cast this pointer to void*, using static_cast
(dynamic_cast has the wrong semantics!), and then, after
recovering the void* in the callback, cast it to the target type
using static_cast. The presence of a void* makes a difference,
the results of static_cast< void* >( p ) are not the same as
those of dynamic_cast< void* >( p ); if p is a Base*, the first
returns the address of the Base sub-object, converted to void*,
and the second the address of the complete object, converted to
void*.
And of course, unless you're casting pointers or references,
dynamic_cast isn't allowed at all. While my personal preference
is for something like "(unsigned long)i", "static_cast< unsigned
long >( i )" is also acceptable, and preferred by others.
[...]
Think of a static_cast of a class type as calling a constructor;
that's what it does, always.
Does dynamic_cast also involve calling a constructor?
dynamic_cast only works with pointers or references, which don't
have constructors.
So it will depend on what
constructors are available. For pointers, you can generally go
back and forth, with a few restrictions: static_cast allows
derived to base even with a virtual base class, but you can't
use static_cast in that case to go back.
Do you mean if A is base with virtual functions and B is derived class
of A, then I can use "static_cast<A*>" on a B*, but I can't
"static_cast<B*>" on an A* object even if the A* object is really
pointing to a B object?
If the inheritance is virtual, yes. Try it:
class A { public: virtual ~A() {} } ;
class B : public virtual A {} ;
int
main()
{
A* pA = new B ;
B* pB = static_cast< B* >( pA ) ;
return 0 ;
}
This shouldn't compile. Replace static_cast with dynamic_cast,
however, and there's no problem.
--
James Kanze (Gabi Software) email: james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34