views:

161

answers:

4

Let's say I have type A, and a derived type B. When I perform a dynamic cast from A* to B*, what kind of "runtime checks" the environment performs? How does it know that the cast is legal?
I assume that in .Net it's possible to use the attached metadata in the object's header, but what happen in C++?

A: 

Dynamic cast performs a runtime check whether this is a valid and doable cast; it'll return NULL when it's not possible to perform the cast.

Chaoz
Or if on a reference type it will throw std::bad_cast
Ben
+2  A: 

Dynamic cast is a two-step process:

  1. Given the vtable of a pointer to an object, use the offset to recover a pointer to the full class. (All adjustments will then be made from this pointer.) This is the equivalent of down-casting to the full class.

  2. Search the type_info of the full class for the type we want - in other words, go through a list of all bases. If we find one, use the offset to adjust the pointer again. If the search in step 2 fails, return NULL.

JRL
A: 

Refere your favourite book on RTTI.

Ashish
+2  A: 

Exact algorithm is compiler-specfic. Here's how it works according to Itanium C++ ABI (2.9.7) standard (written after and followed by GCC).

Pointer to base class is a pointer to the middle of the body of the "big" class. The body of a "big" class is assembled in such a way, that whatever base class your pointer points to, you can uniformly access RTTI for that "big" class, which your "base" class in fact is. This RTTI is a special structure that relates to the "big" class information: of what type it is, what bases it has and at what offsets they are.

In fact, it is the "metadata" of the class, but in more "binary" style.

V instance;
Base *v = &instance;
dynamic_cast<T>(v);

Dynamic cast makes use of the fact that when you write dynamic_cast<T>(v), the compiler can immediately identify metadata for the "big" class of v -- i.e. V! When you write it, you think that T is more derived than Base, so compiler will have hard time doing base-to-drived cast. But compiler can immediately (at runtime) determine most deirved type--V--and it only has then to traverse the inheritance graph contained in metadata to check whether it can downcast V to T. If it can, it just checks the offset. If it can't or is amboguous -- returns NULL.

Pavel Shved