Run-Time Type Identification (RTTI)
Run-time type information may be new to you because it is not found in non-polymorphic languages, such as C. In non-polymorphic languages there is no need for run-time type information because the type of each object is known at compile time (i.e., when the program is written). However, in polymorphic languages such as C++, there can be situations in which the type of an object is unknown at compile time because the precise nature of that object is not determined until the program is executed. C++ implements polymorphism through the use of class hierarchies, virtual functions, and base-class pointers. Since base-class pointers may be used to point to objects of the base class or any object derived from that base, it is not always possible to know in advance what type of object will be pointed to by a base pointer at any given moment in time. This determination must be made at run time, using run-time type identification.
Note : A class that declares or inherits a virtual function is called a polymorphic class.
typeid
To obtain an object's type, use typeid.
You must include the header <typeinfo> in order to use typeid.
Its most commonly used form is shown here:
typeid(object)
Here, object is the object whose type you will be obtaining. 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);const char *name( );
The overloaded == and != provide for the comparison of types. The before() function returns true if the invoking object is before the object used as a parameter in collation order(This function is mostly for internal use only. Its return value has nothing to do with inheritance or class hierarchies) The name() function returns a pointer to the name of the type.
The most important use of typeid occurs when it is applied through a pointer of a polymorphic base class. In this case, 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. (Remember, a base-class pointer can point to objects of the base class or of any class derived from that base.) Thus, using typeid, you can determine at run time the type of the object that is being pointed to by a base-class pointer.
The following program demonstrates this principle.
// An example that uses typeid on a polymorphic class hierarchy.
#include <iostream>#include <typeinfo>using namespace std;
class Mammal {public:virtual bool lays_eggs() { return false; } // Mammal is polymorphic class// ...};
class Cat: public Mammal {public:// ...};
class Platypus: public Mammal {public:bool lays_eggs() { return true; }// ...};
int main(){Mammal *p, AnyMammal;Cat cat;Platypus platypus;
p = &AnyMammal;cout << "p is pointing to an object of type ";cout << typeid(*p).name() << endl;
p = &cat;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 ";cout << typeid(*p).name() << endl;
return 0;}
The output produced by this program is shown here:
p is pointing to an object of type class Mammalp is pointing to an object of type class Catp is pointing to an object of type class Platypus
As explained, when typeid is applied to a base-class pointer of a polymorphic type, the type of object pointed to will be determined at run time, as shown by the output produced by the program. In all cases, when typeid is applied to a pointer of a nonpolymorphic class hierarchy, then the base type of the pointer is obtained. That is, no determination of what that pointer is actually pointing to is made.
For example, comment out the virtual keyword before the function lays_eggs() in Mammal and then compile and run the program.
You will see the following output.
p is pointing to an object of type class Mammalp is pointing to an object of type class Mammalp is pointing to an object of type class Mammal
Since Mammal is no longer a polymorphic class, the type of each object will be Mammal because that is the type of the pointer.
Since typeid is commonly applied to a dereferenced pointer (i.e., one to which the *operator has been applied), a special exception has been created to handle the situation in which the pointer being dereferenced is null. In this case, typeid throws bad_typeid.
References to an object of a polymorphic class hierarchy work the same as pointers. When typeid is applied to a reference to an object of a polymorphic class, it will return the type of the object actually being referred to, which may be of a derived type. The circumstance where you will most often make use of this feature is when objects are passed to functions by reference.
For example, in the following program,
the function WhatMammal() declares a reference parameter to objects of type Mammal. This means that WhatMammal() can be passed references to objects of type Mammal or any class derived from Mammal. When the typeid operator is applied to this parameter, it returns the actual type of the object being passed.
// Use a reference with typeid.
#include <iostream>#include <typeinfo>using namespace std;
class Mammal {public:virtual bool lays_eggs() { return false; }// Mammal is polymorphic// ...};
class Cat: public Mammal {public:// ...};
class Platypus: public Mammal {public:bool lays_eggs() { return true; }// ...};
// Demonstrate typeid with a reference parameter.void WhatMammal(Mammal &ob){cout << "ob is referencing an object of type ";cout << typeid(ob).name() << endl;}
int main(){Mammal AnyMammal;Cat cat;Platypus platypus;WhatMammal(AnyMammal);WhatMammal(cat);WhatMammal(platypus);return 0;}
The output produced by this program is shown here:
ob is referencing an object of type class Mammalob is referencing an object of type class Catob is referencing an object of type class Platypus
There is a second form of typeid that takes a type name as its argument. This form is shown here:
typeid(type-name)
For example, the following statement is perfectly acceptable:
cout << typeid(int).name();
The main use of this form of typeid is to obtain a type_info object that describes the specified type so that it can be used in a type comparison statement. For example, this form of WhatMammal() reports that cats don't like water:
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";}

0 comments:
Post a Comment