#include <iostream>
#include <typeinfo> // Header for typeid operator
using namespace std;
// Base class
class MyBase {
public:
virtual void Print() {
cout << "Base class" << endl;
};
};
// Derived class
class MyDerived : public MyBase {
public:
void Print() {
cout << "Derived class" << endl;
};
};
int main()
{
// Using typeid on built-in types types for RTTI
cout << typeid(100).name() << endl;
cout << typeid(100.1).name() << endl;
// Using typeid on custom types for RTTI
MyBase* b1 = new MyBase();
MyBase* d1 = new MyDerived();
MyBase* ptr1;
ptr1 = d1;
cout << typeid(*b1).name() << endl;
cout << typeid(*d1).name() << endl;
cout << typeid(*ptr1).name() << endl;
if ( typeid(*ptr1) == typeid(MyDerived) ) {
cout << "Ptr has MyDerived object" << endl;
}
// Using dynamic_cast for RTTI
MyDerived* ptr2 = dynamic_cast<MyDerived*> ( d1 );
if ( ptr2 ) {
cout << "Ptr has MyDerived object" << endl;
}
}
OUTPUT:
i
d
6MyBase
9MyDerived
9MyDerived
Ptr has MyDerived object
Ptr has MyDerived object
Monday, December 6, 2010
RTTI examples
RTTI -Notes - dynamic_cast
Runtime Type Information (RTTI) is the concept of determining the type of any variable during execution (runtime.) The RTTI mechanism contains:
The first dynamic_cast statement will work because we cast from derived to base. The second dynamic_cast statement will produce a compilation error because base to derived conversion is not allowed with dynamic_cast unless the base class is polymorphic.
If a class is polymorphic then dynamic_cast will perform a special check during execution. This check ensures that the expression is a valid and complete object of the requested class.
Take a look at the example:
In the example we perform two dynamic_casts from pointer objects of type Base_Class* (namely ptr_a and ptr_b) to a pointer object of type Derived_Class*.
If everything goes well then the first one should be successful and the second one will fail. The pointers ptr_a and ptr_b are both of the type Base_Class. The pointer ptr_a points to an object of the type Derived_Class. The pointer ptr_b points to an object of the type Base_Class. So when the dynamic type cast is performed then ptr_a is pointing to a full object of class Derived_Class, but the pointer ptr_b points to an object of class Base_Class. This object is an incomplete object of class Derived_Class; thus this cast will fail!
Because this dynamic_cast fails a null pointer is returned to indicate a failure. When a reference type is converted with dynamic_cast and the conversion fails then there will be an exception thrown out instead of the null pointer. The exception will be of the type bad_cast.
With dynamic_cast it is also possible to cast null pointers even between the pointers of unrelated classes.
Dynamic_cast can cast pointers of any type to void pointer(void*).
- The operator dynamic_cast
- The operator typeid
- The struct type_info
Dynamic_cast
The dynamic_cast can only be used with pointers and references to objects. It makes sure that the result of the type conversion is valid and complete object of the requested class. This is way a dynamic_cast will always be successful if we use it to cast a class to one of its base classes. Take a look at the example:
class Base_Class { };
class Derived_Class: public Base_Class { };
Base_Class a; Base_Class * ptr_a;
Derived_Class b; Derived_Class * ptr_b;
ptr_a = dynamic_cast<Base_Class *>(&b);
ptr_b = dynamic_cast<Derived_Class *>(&a);
If a class is polymorphic then dynamic_cast will perform a special check during execution. This check ensures that the expression is a valid and complete object of the requested class.
Take a look at the example:
// dynamic_cast
#include <iostream>
#include <exception>
using namespace std;
class Base_Class { virtual void dummy() {} };
class Derived_Class: public Base_Class { int a; };
int main () {
try {
Base_Class * ptr_a = new Derived_Class;
Base_Class * ptr_b = new Base_Class;
Derived_Class * ptr_c;
ptr_c = dynamic_cast< Derived_Class *>(ptr_a);
if (ptr_c ==0) cout << "Null pointer on first type-cast" << endl;
ptr_c = dynamic_cast< Derived_Class *>(ptr_b);
if (ptr_c ==0) cout << "Null pointer on second type-cast" << endl;
} catch (exception& my_ex) {cout << "Exception: " << my_ex.what();}
return 0;
}
If everything goes well then the first one should be successful and the second one will fail. The pointers ptr_a and ptr_b are both of the type Base_Class. The pointer ptr_a points to an object of the type Derived_Class. The pointer ptr_b points to an object of the type Base_Class. So when the dynamic type cast is performed then ptr_a is pointing to a full object of class Derived_Class, but the pointer ptr_b points to an object of class Base_Class. This object is an incomplete object of class Derived_Class; thus this cast will fail!
Because this dynamic_cast fails a null pointer is returned to indicate a failure. When a reference type is converted with dynamic_cast and the conversion fails then there will be an exception thrown out instead of the null pointer. The exception will be of the type bad_cast.
With dynamic_cast it is also possible to cast null pointers even between the pointers of unrelated classes.
Dynamic_cast can cast pointers of any type to void pointer(void*).
RTTI - Notes - typeid
type_id:
In C++, the typeid keyword is used to determine the class of an object at runtime.
In C++, the typeid keyword is used to determine the class of an object at runtime.
#include <iostream> #include <typeinfo> //for 'typeid' to work class Person { public: // ... Person members ... virtual ~Person() {} }; class Employee : public Person { // ... Employee members ... }; int main () { Person person; Employee employee; Person *ptr = &employee; // The string returned by typeid::name is implementation-defined std::cout << typeid(person).name() << std::endl; // Person (statically known at compile-time) std::cout << typeid(employee).name() << std::endl; // Employee (statically known at compile-time) std::cout << typeid(ptr).name() << std::endl; // Person * (statically known at compile-time) std::cout << typeid(*ptr).name() << std::endl; // Employee (looked up dynamically at run-time // because it is the dereference of a // pointer to a polymorphic class) }
Subscribe to:
Posts (Atom)