TITLE: new C++ language casts

PROBLEM: bmainlan@magnus.acs.ohio-state.edu (Dr. G. Bruce Mainland)

   Compilers are just now beginning to support RTTI, yet the only information
   that I have been able to find concerning the topic is in the ANSI draft
   standard; needless to say, the draft is a bit confusing. I am not entirely
   clear as to exactly what the differences between the different types of
   casts are (dynamic_cast, static_cast, etc.).  Could someone please post a
   summary of the new RTTI features of C++ (no, there's nothing in the FAQ
   about RTTI)?


RESPONSE: 

RM = rmartin@oma.com (Robert C. Martin), 18 Dec 95
JK = kanze@gabi-soft.fr (J. Kanze)

RM:

There is a very good description of the new casts in:

	The Design and Evolution of C++, Bjarne Stroustrup, Addison Wesley

The jist of it is as follows:

   static_cast<T>(e)  Will cast the expression e to the type T iff
                      T can be cast to the type of e "implicitly".
                      i.e. static_cast can be used for downcasting; or
                      casting that involves loss of significance.
JK:

The inverse of any standard conversion may also be performed.  Thus, you
can also upcast.  As static_cast's are unchecked, it would strongly
recommend against doing this in general.  Similarly, int's can be cast
to enum's.

RM:

   const_cast<T>(e)   Will cast the expression e to the type T iff the
                      difference between the type of e and T is a
                      matter of 'const'.  i.e. can cast away const, or
                      can cast *to* const.

JK:

Despite the name, const_cast is also used to change the volatile
qualifier as well.

RM:

   reinterpret_cast<T>(e)  Will cast the expression e to the type T.
                      This is the old sledgehammer cast.

   dynamic_cast<T>(e) Will cast the expression e to the type T as a
                      static_cast unless e is a pointer to a class
                      with at least one virtual function, in which
                      case it casts to T iff there is an implicit cast
                      from T to the true run-time type of e.  If not,
                      it returns zero.

struct B {virtual ~B();};  // class with virtual function.
struct D : B {};
struct E : B {};


void f(B* theB)
{
  D* dp = dynamic_cast<D*>(theB);
  if (dp) // theB really points to a D,
  {}
}

JK:

When upcasting, dynamic_cast is checked, static_cast no.

There are two particular cases:

1. When casting to void*, static_cast uses the static type of the
expression, dynamic_cast the dynamic type.

2. When upcasting, you cannot use static_cast to cast up from a virtual
base class.  You can use dynamic_cast.

I might add that when casting pointers, dynamic_cast returns NULL if the
type is wrong, whereas when casting references, it throws an exception.
Thus, if you really don't know the type, cast pointers, not references.
(If you do know the dynamic type, then you could also use static_cast,
although dynamic_cast will ensure that your knowledge is not mistaken.)

RM:

The other RTTI feature of C++ is the keyword typeid.

typeid(e);  returns a reference to an instance of a type_info class.
This class is guaranteed to have two member functions: (actually there
are more, but we don't need to discuss them here.)

	class type_info
	{
          public:
            const char* name() const;
            bool operator==(const type_info&) const;
	};

So you can write code like this:

   if (typeid(x) == typeid(Square)) // makes sure that x is a Square.
