Anda di halaman 1dari 19

Run-Time Type ID and the

Casting Operators
Run-Time Type Identification
(RTTI)
• Added to provide enhanced support for run-time
polymorphism.
• To identify the type of an object during the
execution of program.
• Reason for req:
– Because of polymorphism, the precise nature of that
object is not determined until the program is
executed.
– base-class pointers may be used to point to objects of
the base class or any object derived from that base
• object's type can be obtained using typeid.

• It is defined in the header <typeinfo>

• There are two ways to extract typeid

• Prototype:
– typeid(object)

• It may be of any type,including the built-in types and


class types that you create.

• typeid returns a reference to an object of type type_info


that describes the type of object.
• The type_info class defines the following public
members:
bool operator==(const type_info &ob);
bool operator!=(const type_info &ob);
bool before(const type_info &ob); /* internal use*/
const char *name( ); /*returns a pointer to the name of
the type.*/
// A simple example that uses typeid.
#include <iostream> if(typeid(i) == typeid(j))
#include <typeinfo> cout << "The types of i and j are the same\n";
using namespace std;
class myclass1 { if(typeid(i) != typeid(f))
// ... cout << "The types of i and f are not the
}; same\n";
class myclass2 {
// ... if(typeid(ob1) != typeid(ob2))
}; cout << "ob1 and ob2 are of differing types\n";
int main() return 0;
{ }
int i, j;
float f;
char *p;
myclass1 ob1;
myclass2 ob2;

cout << "The type of i is: " << typeid(i).name<< endl;


cout << "The type of f is: " << typeid(f).name() << endl;
cout << "The type of p is: " << typeid(p).name() << endl;
cout << "The type of ob1 is: " << typeid(ob1).name() << endl;
cout << "The type of ob2 is: " << typeid(ob2).name() << "\n\n";
Output:
The type of i is: int
The type of f is: float
The type of p is: char *
The type of ob1 is: class myclass1
The type of ob2 is: class myclass2
The types of i and j are the same
The types of i and f are not the same
ob1 and ob2 are of differing types

• When a pointer of a polymorphic base class,it will


automatically return the type of the actual object being
pointed to, which may be a base-class object or an
object derived from that base.
// An example that uses typeid on a int main()
polymorphic class hierarchy. {
#include <iostream> Mammal *p, AnyMammal;
#include <typeinfo> Cat cat;
using namespace std; Platypus platypus;
p = &AnyMammal;
class Mammal { cout << "p is pointing to an object of type ";
public: cout << typeid(*p).name() << endl;
virtual bool lays_eggs() { return false; }// p = &cat;
Mammal is polymorphic
cout << "p is pointing to an object of type ";
// ...
cout << typeid(*p).name() << endl;
};
p = &platypus;
cout << "p is pointing to an object of type ";
class Cat: public Mammal { cout << typeid(*p).name() << endl;
public: return 0;
// ...
}
};

class Platypus: public Mammal {


public:
bool lays_eggs() { return true; } Output:
// ... p is pointing to an object of type class Mammal
};
p is pointing to an object of type class Cat
p is pointing to an object of type class Platypus
• typeid is commonly applied to a
dereferenced pointer
• special exception has been created when
the pointer being dereferenced is null.
• In this case, typeid throws bad_typeid
• Other way of defining typeid,
– typeid(type-name)

void WhatMammal(Mammal &ob)


{
cout << "ob is referencing an object of type ";
cout << typeid(ob).name() << endl;
if(typeid(ob) == typeid(Cat))
cout << "Cats don't like water.\n";
}
A Simple Application of Run-Time Type ID
#include <iostream> int main()
using namespace std; {
class Mammal { Mammal *ptr; // pointer to base class
public: int i;
virtual bool lays_eggs() { return false; }// Mammal is polymorphic int c=0, d=0, p=0;
// ... // generate and count objects
}; for(i=0; i<10; i++) {
class Cat: public Mammal { ptr = factory(); // generate an object
public: cout << "Object is " << typeid(*ptr).name();
// ... cout << endl;
}; // count it
class Platypus: public Mammal { if(typeid(*ptr) == typeid(Dog)) d++;
public: if(typeid(*ptr) == typeid(Cat)) c++;
bool lays_eggs() { return true; } if(typeid(*ptr) == typeid(Platypus)) p++;
// ... }
}; cout << endl;
class Dog: public Mammal { cout << "Animals generated:\n";
public: cout << " Dogs: " << d << endl;
// ... cout << " Cats: " << c << endl;
}; cout << " Platypuses: " << p << endl;
return 0;
// A factory for objects derived from Mammal. }
Mammal *factory()
{
switch(rand() % 3 ) {
case 0: return new Dog;
case 1: return new Cat;
case 2: return new Platypus;
}
return 0;
}
• Output:

Object is class Platypus


Object is class Platypus
Object is class Cat
Object is class Cat
Object is class Platypus
Object is class Cat
Object is class Dog
Object is class Dog
Object is class Cat
Object is class Platypus

Animals generated:
Dogs: 2
Cats: 4
Platypuses: 4
typeid in Template Classes

• The type of an object is determined by what data


is used for its generic data when the object is
instantiated.
• Two instances of the same template class using
different data are therefore different types.
// Using typeid with templates. Output:
#include <iostream>
using namespace std; Type of o1 is class myclass<int>
template <class T> class myclass { Type of o2 is class myclass<int>
T a; Type of o3 is class myclass<double>
public:
myclass(T i) { a = i; }
// ... o1 and o2 are the same type
}; o1 and o3 are different types
int main()
{
myclass<int> o1(10), o2(9);
myclass<double> o3(7.2);
cout << "Type of o1 is ";
cout << typeid(o1).name() << endl;
cout << "Type of o2 is ";
cout << typeid(o2).name() << endl;
cout << "Type of o3 is ";
cout << typeid(o3).name() << endl;
cout << endl;
if(typeid(o1) == typeid(o2))
cout << "o1 and o2 are the same type\n";
if(typeid(o1) == typeid(o3))
cout << "Error\n";
else
cout << "o1 and o3 are different types\n";
return 0;
}
The Casting Operators
• C++ defines five casting operators
– the traditional-style cast inherited from C.
– dynamic_cast
– const_cast
– reinterpret_cast
– static_cast
dynamic_cast
• Performs a run-time cast that verifies the validity
of a cast.
• General form:
– dynamic_cast<target-type> (expr)

• target-type -> target type of the cast

• The target type must be a pointer or reference


type
• expression being cast must evaluate to a pointer
or reference
• purpose of dynamic_cast is to perform casts on
polymorphic types
• dynamic_cast will succeed if the pointer (or reference)
being cast is a pointer (or reference) to either an object
of the target type or an object derived from the target
type
• If a dynamic_cast on reference types fails, a bad_cast
exception is thrown
Base *bp, b_ob;
Derived *dp, d_ob;
bp = &d_ob; // base pointer points to Derived object
dp = dynamic_cast<Derived *> (bp); // cast to derived
pointer OK
if(dp) cout << "Cast OK";

• the cast from the base pointer bp to the derived pointer


dp works because bp is actually pointing to a Derived
object.
bp = &b_ob; // base pointer points to Base object
dp = dynamic_cast<Derived *> (bp); // error
if(!dp) cout << "Cast Fails";

Here the cast fails & displays Cast Fails

Anda mungkin juga menyukai