Skip to main content

Polymorphic class and RTTI mechanisms

Short answer

A polymorphic class has at least one virtual function. RTTI uses dynamic_cast for safe downcasting (returns null if wrong type) and typeid for type comparison/name. Example: Animal* pointer to Dog or Cat; dynamic_cast<Dog*> demonstates safe Dog-specific calls.

What do you mean by polymorphic class? What are different RTTI mechanisms in C++? Write a program that shows both RTTI mechanisms.

Polymorphic class

A class that has at least one virtual function (declared or inherited) is a polymorphic class. Its objects carry a hidden vptr, so the run-time type of an object referred to by a base pointer or reference can be found. RTTI works only for polymorphic classes.

RTTI mechanisms

Run-Time Type Information lets a program find the real type of an object at run time. C++ gives two mechanisms:

  1. dynamic_cast – safely converts a base pointer/reference to a derived pointer/reference. For pointers it returns NULL if the object is not of that type (for references it throws bad_cast).
  2. typeid operator – returns a type_info object (header <typeinfo>) describing the type of an expression. Its name() gives the type name and == compares types.

Program showing both

#include <iostream>
#include <typeinfo>
using namespace std;

class Animal {                       // polymorphic: has virtual function
public:
    virtual void speak() { cout << "Animal sound\n"; }
    virtual ~Animal() {}
};
class Dog : public Animal {
public:
    void speak() { cout << "Dog barks\n"; }
    void fetch() { cout << "Dog fetches the ball\n"; }
};
class Cat : public Animal {
public:
    void speak() { cout << "Cat meows\n"; }
};

int main() {
    Animal *a[2] = { new Dog, new Cat };

    for (int i = 0; i < 2; i++) {
        // mechanism 1: typeid
        cout << "Type: " << typeid(*a[i]).name() << endl;
        if (typeid(*a[i]) == typeid(Dog))
            cout << "typeid says it is a Dog\n";

        // mechanism 2: dynamic_cast
        Dog *d = dynamic_cast<Dog*>(a[i]);
        if (d != NULL)
            d->fetch();              // safe: object really is a Dog
        else
            cout << "dynamic_cast failed: not a Dog\n";
    }
    for (int i = 0; i < 2; i++) delete a[i];
    return 0;
}

The name() string is compiler dependent (e.g. 3Dog in GCC). For the Dog object both tests succeed; for the Cat object dynamic_cast returns NULL.

✓ Answer checked by Claude Opus 5.5 (high effort)

All Object Oriented Programming chapter 7 questions →