RTTI (Run-Time Type Information) allows a C++ program to identify the actual type of an object while the program is running. It plays an important role when working with inheritance and polymorphism.
- It is mainly used when you work with classes that have virtual functions (polymorphic classes).
- Upcasting means converting a derived class object to a base class type. This is safe because the derived class has all attributes of base class.
- Downcasting means converting a base class pointer or reference back to a derived class type. This requires a runtime check to ensure the conversion is valid.
Runtime Cast
A runtime cast is a type conversion that checks its validity during program execution, typically used to safely downcast a base class pointer or reference to a derived class in an inheritance hierarchy.
- Ensures type safety at runtime.
- Implemented using
dynamic_cast. - Returns a valid pointer if the cast is correct, or
nullptr(for pointers) if it fails.
Upcasting
- It Enables polymorphism, allowing derived objects to be accessed through base class interfaces.
- It is safe because every derived class object is also a base class object.
- It happens implicitly; no explicit cast is needed in most cases.
#include <iostream>
using namespace std;
class Base
{
public:
void show()
{
cout << "Base class\n";
}
};
class Derived : public Base
{
public:
void show()
{
cout << "Derived class\n";
}
};
int main()
{
Derived d;
// Upcasting: Derived object treated as Base
Base *b = &d;
b->show();
return 0;
}
Output
Base class
Downcasting
- Allows access to derived class-specific members when working through a base class pointer or reference.
- It is commonly used in polymorphic class hierarchies where the actual object type is determined at runtime.
- It is not inherently safe — the base pointer may not actually point to a derived class object.
#include <iostream>
using namespace std;
class Base
{
public:
virtual void dummy()
{
} // Make Base polymorphic
};
class Derived : public Base
{
public:
void show()
{
cout << "Derived class\n";
}
};
int main()
{
Base *b = new Derived;
// Downcasting: Convert Base pointer back to Derived pointer
Derived *d = dynamic_cast<Derived *>(b);
if (d != nullptr)
d->show();
else
cout << "Cannot cast";
delete b;
return 0;
}
Output
Derived class