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:
 
//: C24:RTTIwithReferences.cpp
#include <cassert>
#include <typeinfo>
using namespace std;
class B {
public:
  virtual float f() { return 1.0;}
  virtual ~B() {}
};
class D : public B { /* ... */ };
int main() {
  B* p = new D;
  B& r = *p;
  assert(typeid(p) == typeid(B*));
  assert(typeid(p) != typeid(D*));
  assert(typeid(r) == typeid(D));
  assert(typeid(*p) == typeid(D));
  assert(typeid(*p) != typeid(B));
  assert(typeid(&r) == typeid(B*));
  assert(typeid(&r) != typeid(D*));
  assert(typeid(r.f()) == typeid(float));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*)
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*)
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:
 
//: C24:RTTIwithExceptions.cpp
#include <typeinfo>
#include <iostream>
using namespace std;
class X { public: virtual ~X(){} };
class B { public: virtual ~B(){} };
class D : public B {};
int main() {
  D d;
  B & b = d; // Upcast to reference
  try {
    X& xr = dynamic_cast<X&>(b);
  } catch(...) {
    cout << "dynamic_cast<X&>(b) failed" 
         << endl;
  }
  X* xp = 0;
  try {
    typeid(*xp); // Throws exception
  } catch(bad_typeid) {
    cout << "Bad typeid() expression" << endl;
  }The
failure, of course, is because 
b
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. 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.
 
  
	
		
		  Contact: webmaster@codeguru.com
		  
		  CodeGuru - the website for developers.