C++ Tutorial

Class and Object

Reference

Inheritance and Derivation

Polymorphism and Virtual Functions

Operator Overloading

Template

Exception

Object Oriented Advanced

Input/Output Stream

File Operations

typeid Operator: Get Type Information in C++

In this tutorial, we will learn about the typeid operator in C++. The typeid operator is part of the C++ Run-Time Type Information (RTTI) system and allows you to obtain information about a type at runtime. You can use the typeid operator to compare the types of two objects, get the name of a type, or perform type-specific operations based on the runtime type of an object.

  • Basic usage of typeid:

Here's a simple example demonstrating the use of the typeid operator:

#include <iostream>
#include <typeinfo>

class Base {
public:
    virtual ~Base() {}
};

class Derived : public Base {};

int main() {
    Base* basePtr = new Derived();

    if (typeid(*basePtr) == typeid(Derived)) {
        std::cout << "The object is of type Derived." << std::endl;
    } else {
        std::cout << "The object is not of type Derived." << std::endl;
    }

    delete basePtr;
    return 0;
}

In this example, we define a Base class and a Derived class that inherits from Base. In the main() function, we create a Base pointer pointing to a Derived object. We use the typeid operator to compare the runtime type of the object pointed to by basePtr with the type Derived. The comparison is true because the object is actually of type Derived.

  • Using typeid with the name() function:

The typeid operator returns a reference to a std::type_info object, which contains information about the type. You can use the name() function to get a human-readable (but compiler-specific) name for a type:

#include <iostream>
#include <typeinfo>

int main() {
    int integer = 5;
    double floating = 3.14;

    std::cout << "Type of integer: " << typeid(integer).name() << std::endl; // Output: Type of integer: int
    std::cout << "Type of floating: " << typeid(floating).name() << std::endl; // Output: Type of floating: double

    return 0;
}

Keep in mind that the names returned by the name() function are compiler-specific and may not be the same across different compilers.

  • Using typeid with polymorphism:

When using typeid on a base class object with virtual functions, it will provide the actual type of the object at runtime, which is useful when working with polymorphic classes:

#include <iostream>
#include <typeinfo>

class Base {
public:
    virtual ~Base() {}
};

class Derived1 : public Base {};
class Derived2 : public Base {};

void printType(Base* basePtr) {
    std::cout << "Type of object: " << typeid(*basePtr).name() << std::endl;
}

int main() {
    Derived1 d1;
    Derived2 d2;

    printType(&d1); // Output: Type of object: Derived1
    printType(&d2); // Output: Type of object: Derived2

    return 0;
}

In this example, we define a Base class and two derived classes, Derived1 and Derived2. We use a printType function that takes a Base pointer and prints the runtime type of the object pointed to by the pointer.

  1. How to use typeid for type identification in C++:

    #include <iostream>
    #include <typeinfo>
    
    int main() {
        int intValue = 42;
        const std::type_info& typeInfo = typeid(intValue);
    
        std::cout << "Type: " << typeInfo.name() << std::endl;
    
        return 0;
    }
    
    • The typeid operator returns type information about an expression.
  2. typeid vs dynamic_cast in C++:

    #include <iostream>
    #include <typeinfo>
    
    class Base {
    public:
        virtual ~Base() {}
    };
    
    class Derived : public Base {};
    
    int main() {
        Base* basePtr = new Derived();
    
        // Using typeid for type identification
        const std::type_info& typeInfo = typeid(*basePtr);
    
        if (typeInfo == typeid(Derived)) {
            std::cout << "Object is of type Derived" << std::endl;
        } else {
            std::cout << "Object is not of type Derived" << std::endl;
        }
    
        delete basePtr;
    
        return 0;
    }
    
    • typeid is used for querying type information, while dynamic_cast is used for safe downcasting in polymorphic classes.
  3. Using typeid with polymorphism in C++:

    #include <iostream>
    #include <typeinfo>
    
    class Shape {
    public:
        virtual ~Shape() {}
    };
    
    class Circle : public Shape {};
    
    int main() {
        Circle circle;
        Shape* shapePtr = &circle;
    
        // Using typeid with polymorphism
        if (typeid(*shapePtr) == typeid(Circle)) {
            std::cout << "Shape is a Circle" << std::endl;
        } else {
            std::cout << "Shape is not a Circle" << std::endl;
        }
    
        return 0;
    }
    
    • typeid can be used with polymorphic classes to identify the actual type of an object.
  4. Type information for user-defined classes with typeid in C++:

    #include <iostream>
    #include <typeinfo>
    
    class MyClass {
        // Class definition
    };
    
    int main() {
        MyClass myObject;
        const std::type_info& typeInfo = typeid(myObject);
    
        std::cout << "Type: " << typeInfo.name() << std::endl;
    
        return 0;
    }
    
    • typeid can be used with user-defined classes to obtain type information.
  5. typeid and exception handling in C++:

    #include <iostream>
    #include <typeinfo>
    
    class MyException : public std::exception {
    public:
        const char* what() const noexcept override {
            return "Custom exception";
        }
    };
    
    int main() {
        try {
            throw MyException();
        } catch (const std::exception& e) {
            // Using typeid in exception handling
            if (typeid(e) == typeid(MyException)) {
                std::cout << "Caught MyException" << std::endl;
            } else {
                std::cout << "Caught a different exception" << std::endl;
            }
        }
    
        return 0;
    }
    
    • typeid can be used in exception handling to identify the type of the caught exception.
  6. typeid and template metaprogramming in C++:

    #include <iostream>
    #include <typeinfo>
    
    template <typename T>
    void printType() {
        const std::type_info& typeInfo = typeid(T);
        std::cout << "Type: " << typeInfo.name() << std::endl;
    }
    
    int main() {
        printType<int>();
        printType<double>();
        printType<std::string>();
    
        return 0;
    }
    
    • typeid can be used in template metaprogramming to obtain type information.
  7. typeid and type traits in C++:

    #include <iostream>
    #include <type_traits>
    #include <typeinfo>
    
    template <typename T>
    void printTypeIfInteger() {
        if (std::is_integral<T>::value) {
            const std::type_info& typeInfo = typeid(T);
            std::cout << "Type is an integer: " << typeInfo.name() << std::endl;
        } else {
            std::cout << "Type is not an integer" << std::endl;
        }
    }
    
    int main() {
        printTypeIfInteger<int>();
        printTypeIfInteger<double>();
    
        return 0;
    }
    
    • typeid can be used in combination with type traits to perform type-specific operations.