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.
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.
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.
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.
[...]
Does dynamic_cast also involve calling a constructor?
dynamic_cast only works with pointers or references, which don't
have constructors.
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.