References
RTTI
must adjust somewhat to work with references. The contrast between pointers and
references occurs because a reference is always dereferenced for you by the
compiler, whereas a pointer’s type
or
the type it points to may be examined. Here’s an example:
class B {
public:
virtual float f() { return 1.0;}
virtual ~B() {}
};
class D : public B { /* ... */ };
B* p = new D;
B& r = *p;
Whereas
the type of pointer that
typeid( )
sees is the base type and not the derived type, the type it sees for the
reference is the derived type:
typeid(p) == typeid(B*)
typeid(p) != typeid(D*)
typeid(r) == typeid(D)
Conversely,
what the pointer points to is the derived type and not the base type, and
taking the address of the reference produces the base type and not the derived
type:
typeid(*p) == typeid(D)
typeid(*p) != typeid(B)
typeid(&r) == typeid(B*)
typeid(&r) != typeid(D*)
Expressions
may also be used with the
typeid( )
operator because they have a type as well:
typeid(r.f())
== typeid(float)
Exceptions
When
you perform a
dynamic_cast
to a reference, the result must be assigned to a reference. But what happens if
the cast fails? There are no null references,
so this is the perfect place to throw an exception; the Standard C++ exception
type is
bad_cast,
but in the following example the ellipses are used to catch any exception:
class X {};
MI mi;
d1 & D1 = mi; // Upcast to reference
try {
X& xr = dynamic_cast<X&>(D1);
} catch(...) {
cout << "dynamic_cast<X&>(D1) failed"
<< endl;
}
The
failure, of course, is because
D1
doesn’t actually point to an
X
object. If an exception was not thrown here, then
xr
would be unbound, and the guarantee that all objects or references are
constructed storage would be broken.
An
exception is also thrown if you try to dereference a null pointer in the
process of calling
typeid( ).
The Standard C++ exception is called
bad_typeid:
B* bp = 0;
try {
typeid(*bp); // Throws exception
} catch(bad_typeid) {
cout << "Bad typeid() expression" << endl;
}
Here
(unlike the reference example above) you can avoid the exception by checking
for a nonzero pointer value before attempting the operation; this is the
preferred practice.
Go to CodeGuru.com
Contact: webmaster@codeguru.com
© Copyright 1997-1999 CodeGuru