By looking at the same stuff dynamic_cast (i.e., vtable).
By static, I mean that there is no reason that the object needs to be tagged
with some type information so that the object type can be detected when you
only have a pointer or reference to a possible base class..
That isn't the definition of static type:
1.3.11 static type
the type of an expression (3.9), which type results from analysis of
the program without considering execution semantics. The static type
of an expression depends only on the form of the program in which the
expression appears, and does not change while the program is
executing.
In addition, an exception does have to be tagged with some "type
information" to allow matching catch blocks to be chosen. The
exception object itself won't contain this information (it may not
have a vtable), but it is there nevertheless, held globally. Some
implementations choose the obvious implementation of holding the
(statically determined) type_info object for the thrown exception.
Others might just hold the lesser information required to check
compatibility with catch blocks.
Nope. Dynamic cast needs additional help because it has no clue what
the object that the pointer/reference actually is (only that it knows what a
permissable base class is). It needs to inspect the object to determine
what the t ype really is.
Yes, that pretty obviously (I thought) what I meant by "in one case
held in the object".
Throwing execptions is different. At compile time essentially the throw code
only has to remember the static type (you can't throw polymorphically) of the
experssion thrown. This is then checked at runtime against the various
catch blocks as it's unwinding the stack. However the value actually thrown
is immaterial, the exception handling code doesn't EVER need to look at it
until it has already found the catch block and needs it to initalize the local
variable there.
Yes, I don't (and haven't) disagreed with any of that. The dynamic
type and static type of an exception are the same at the throw site
(since whatever the dynamic type of the object thrown, a copy is made
of the static type). At the catch site they can be different of
course.
I think this thread might come to a close quicker if I clarified.
1. dynamic_cast checks to see whether the dynamic type of the passed
object *is a subclass of* the cast-to type.
2. catch blocks check to see whether the thrown exception type *is a
subclass of* the caught type.
3. Both these checks must occur at runtime. The dynamic type of an
object is not generally known at compile time. The type of an
exception caught by a particular catch is not known at compile time.
4. Exceptions don't need to have any information stored inside them
about their dynamic type, since the compiler can store it in a "global
datum" at the throw point. Some compilers store the statically
determined type_info object for the thrown type, but their are many
alternatives, such as storing an index into a throw/catch
compatibility matrix.
5. Objects (with virtual functions) do need to have information stored
along with them in order to implement dynamic_cast. This is because
their are many objects in existence at once, so you can't store a
single "global datum" to tell you the type as you can with exceptions
(of which there is only one at a time). Most compilers store a pointer
to the type_info for an object in the type's vtable, but alternative
implementations, such as storing an index into an object creation/cast
target compatibility matrix directly in the object, are possible.
6. Some descriptive definitions of RTTI exclude dynamic_cast. Others
include exception handling.
The points of others that I have disagreed with:
1. Exception handling doesn't require a runtime check for
compatibility of types.
2. The compatibility check required for exception handling is
substantially different to the check required by dynamic_cast. I have
stated the differences (need to store information associated with each
object for dynamic_cast), but this seemed to be disagreed with.
3. Various definitions of RTTI. There is no formal definition that
I've been able to find. Possibilities include prescriptive ones
(dynamic_cast, typeid, the contents of <typeinfo> (and catch block
matching according to some)), descriptive ones (constructs requiring
checking or identification of types at runtime, constructs requiring
information to be stored in each object relating to its type). I have
pointed out the inadequacy of some vague descriptive definitions,
since they either include catch block matching or exclude dynamic_cast
from RTTI, which I assume wasn't the intent (since the poster in
question was insisting that exception handling has nothing to do with
RTTI, yet dynamic_cast is RTTI). Other definitions talk in terms of
implementation (constructs requiring information to be stored in each
object relating to its type), and therefore seem to me to be poor
definitions.
4. Comments that "is a type of" is the same as "requires".
Tom