# Runtime Type Information

## Runtime Type and Polymorphism with Example code

Runtime type and polymorphism are important concepts in object-oriented programming. In Java, these concepts are closely related to inheritance and method overriding.

Polymorphism refers to the ability of objects of different classes to be used interchangeably. This is achieved through inheritance and method overriding. When a method is overridden in a subclass, it can be called using a reference to an object of the superclass or the subclass, and the implementation of the method that is executed depends on the runtime type of the object.

Here's an example code that demonstrates runtime type and polymorphism in Java:

```cpp
class Animal {
    public void makeSound() {
        System.out.println("The animal makes a sound");
    }
}

class Dog extends Animal {
    public void makeSound() {
        System.out.println("The dog barks");
    }
}

class Cat extends Animal {
    public void makeSound() {
        System.out.println("The cat meows");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal a1 = new Animal();
        Animal a2 = new Dog();
        Animal a3 = new Cat();
        
        a1.makeSound(); // prints "The animal makes a sound"
        a2.makeSound(); // prints "The dog barks"
        a3.makeSound(); // prints "The cat meows"
    }
}
```

In this example, we have a superclass `Animal` and two subclasses `Dog` and `Cat`. Each class has a `makeSound()` method which is overridden in the subclasses. In the `main()` method, we create three objects: one of type `Animal`, one of type `Dog`, and one of type `Cat`. We then call the `makeSound()` method on each object.

When we call `a1.makeSound()`, the `makeSound()` method of the `Animal` class is executed, because `a1` is of type `Animal`. When we call `a2.makeSound()`, the `makeSound()` method of the `Dog` class is executed, because `a2` is of type `Dog`. Similarly, when we call `a3.makeSound()`, the `makeSound()` method of the `Cat` class is executed, because `a3` is of type `Cat`.

This demonstrates the polymorphic behavior of the `makeSound()` method. At runtime, the implementation of the method that is executed depends on the runtime type of the object.

## type\_info Class in CPP

In C++, the `type_info` class is part of the `<typeinfo>` header and is used to obtain information about the type of an object at runtime. It is a standard class that is defined in the C++ Standard Library.

The `type_info` class is typically used in conjunction with the `typeid` operator, which is used to obtain a `type_info` object representing the type of an object. Here's an example:

```cpp
#include <iostream>
#include <typeinfo>

int main() {
    int i = 42;
    const std::type_info& ti = typeid(i);
    std::cout << ti.name() << std::endl;
    return 0;
}
```

In this example, we declare an `int` variable `i` and obtain a `type_info` object representing its type using the `typeid` operator. We then print the name of the type using the `name()` method of the `type_info` object.

The output of this program will depend on the implementation, but it will typically be a mangled name that represents the type of the object. For example, on a typical Linux system, the output might be something like:

```
i
```

This indicates that the type of the object is `int`.

The `type_info` class also provides a `before()` method, which can be used to compare two `type_info` objects to determine their relative order in the implementation-defined hierarchy of types. This can be useful for implementing type-safe dynamic casting and other type-related operations.

It's worth noting that the `type_info` class and the `typeid` operator are part of the RTTI (Run-Time Type Information) feature of C++, which enables type-safe dynamic casting and other type-related operations at runtime. However, the use of RTTI can have some performance overhead and can make code less portable, so it's important to use it judiciously.

## typeid Operator

In C++, the `typeid` operator is used to obtain information about the type of an object at runtime. It returns a `type_info` object that represents the type of the expression passed as an argument.

Here's an example:

```cpp
#include <iostream>
#include <typeinfo>

int main() {
    int i = 42;
    const std::type_info& ti = typeid(i);
    std::cout << ti.name() << std::endl;
    return 0;
}
```

In this example, we declare an `int` variable `i` and obtain a `type_info` object representing its type using the `typeid` operator. We then print the name of the type using the `name()` method of the `type_info` object.

The output of this program will depend on the implementation, but it will typically be a mangled name that represents the type of the object. For example, on a typical Linux system, the output might be something like:

```
i
```

This indicates that the type of the object is `int`.

The `typeid` operator can also be used with pointers and references. When used with a pointer or reference, `typeid` returns the type of the pointed-to or referred-to object. Here's an example:

```cpp
#include <iostream>
#include <typeinfo>

class Animal {
public:
    virtual void makeSound() {}
};

class Dog : public Animal {
public:
    void makeSound() override {
        std::cout << "The dog barks" << std::endl;
    }
};

int main() {
    Dog d;
    Animal* a = &d;
    const std::type_info& ti1 = typeid(d);
    const std::type_info& ti2 = typeid(*a);
    std::cout << ti1.name() << std::endl;
    std::cout << ti2.name() << std::endl;
    return 0;
}
```

In this example, we have a `Dog` class that derives from an `Animal` class. We create a `Dog` object `d` and obtain a `type_info` object representing its type using the `typeid` operator. We also obtain a `type_info` object representing the type of the `Animal` object pointed to by the `Animal` pointer `a` using the `typeid` operator.

The output of this program will depend on the implementation, but it will typically be something like:

```
3Dog
5Animal
```

This indicates that the type of the `Dog` object is `Dog` and the type of the `Animal` object is `Animal`.

The `typeid` operator is often used in conjunction with RTTI (Run-Time Type Information) to implement type-safe dynamic casting and other type-related operations at runtime. However, the use of RTTI can have some performance overhead and can make code less portable, so it's important to use it judiciously.

## Compiler Options

Compiler options are command-line arguments that are passed to a compiler to control its behavior. These options can be used to customize the compilation process, optimize code, enable or disable certain features, and more.

Here are some common compiler options that can be used with the GCC (GNU Compiler Collection) compiler:

* `-c`: Compile source files without linking.
* `-o` \<output file>: Specify the name of the output file.
* `-g`: Generate debug information.
* `-O` \<level>: Enable optimization at the specified level (0-3).
* `-Wall`: Enable all warnings.
* `-Wextra`: Enable extra warnings.
* `-pedantic`: Enable strict ISO C++ compliance.
* `-std=`\<standard>: Specify the language standard to use (e.g., `-std=c++17`).
* `-I`\<directory>: Add a directory to the list of directories searched for include files.
* `-L`\<directory>: Add a directory to the list of directories searched for libraries.
* `-l`\<library>: Link with the specified library.
* `-D`\<macro>=\<value>: Define a macro with the specified value.
* `-U`\<macro>: Undefine a macro.

These options can be used in combination with one another to achieve specific compilation goals. For example, to compile a C++ program with optimization level 3, generate debug information, and enable all warnings, you might use the following command:

```
g++ -O3 -g -Wall main.cpp -o program
```

This will compile the `main.cpp` source file with optimization level 3, generate debug information, enable all warnings, and produce an output file named `program`.

It's important to note that different compilers may have different options and behaviors, so it's always a good idea to consult the documentation for your specific compiler for more information.

## Safe Pointer Conversions

In C++, safe pointer conversions refer to the process of converting pointers from one type to another in a way that preserves type safety and avoids undefined behavior. There are several ways to perform safe pointer conversions in C++, including static\_cast, dynamic\_cast, reinterpret\_cast, and const\_cast.

1. `static_cast`: This is a compile-time cast that can be used to convert a pointer of one type to a pointer of another type, as long as the conversion is safe. For example, you can use `static_cast` to convert a pointer to a derived class to a pointer to its base class, or to convert a `void*` pointer to another pointer type. However, if the conversion is not safe, `static_cast` can lead to undefined behavior.
2. `dynamic_cast`: This is a run-time cast that can be used to convert a pointer of one type to a pointer of another type, as long as the conversion is safe and the object being pointed to is of the target type or a derived type. If the object is not of the target type or a derived type, `dynamic_cast` returns a null pointer. This can be useful for implementing safe type casting and polymorphic behavior.
3. `reinterpret_cast`: This is a cast that can be used to convert a pointer of one type to a pointer of another type, regardless of their relationship. However, `reinterpret_cast` can lead to undefined behavior if the pointer types are not compatible.
4. `const_cast`: This is a cast that can be used to remove the constness of a pointer or reference. This can be useful for implementing const-correctness, but it should be used with care to avoid introducing undefined behavior.

Here is an example that demonstrates safe pointer conversions using `static_cast` and `dynamic_cast`:

```cpp
#include <iostream>

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

class Dog : public Animal {
public:
    void bark() {
        std::cout << "Woof!" << std::endl;
    }
};

int main() {
    Dog d;
    Animal* a = &d;

    // safe pointer conversion using static_cast
    Dog* d1 = static_cast<Dog*>(a);
    d1->bark();

    // safe pointer conversion using dynamic_cast
    Dog* d2 = dynamic_cast<Dog*>(a);
    if (d2) {
        d2->bark();
    }

    return 0;
}
```

In this example, we have a `Dog` class that derives from an `Animal` class. We create a `Dog` object `d` and obtain a pointer to it using a pointer to its base class, `Animal`. We then perform two safe pointer conversions: one using `static_cast` to convert the `Animal` pointer to a `Dog` pointer, and one using `dynamic_cast` to convert the `Animal` pointer to a `Dog` pointer. We then call the `bark()` method on the resulting `Dog` pointers to demonstrate that the conversions were successful.

Note that `dynamic_cast` returns a null pointer if the conversion is not safe, so it is important to check the result before using the resulting pointer.

## Dynamic Cast in CPP

In C++, `dynamic_cast` is a run-time cast operator that can be used to safely convert pointers or references to classes up or down a class hierarchy. Unlike `static_cast`, `dynamic_cast` performs a run-time check to ensure that the conversion is valid and returns a null pointer if the conversion is not possible.

Here's an example that demonstrates the use of `dynamic_cast`:

```cpp
#include <iostream>

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

class Dog : public Animal {
public:
    void bark() {
        std::cout << "Woof!" << std::endl;
    }
};

class Cat : public Animal {
public:
    void meow() {
        std::cout << "Meow!" << std::endl;
    }
};

int main() {
    Animal* a1 = new Dog();
    Animal* a2 = new Cat();

    Dog* d1 = dynamic_cast<Dog*>(a1);
    if (d1) {
        d1->bark();
    }

    Dog* d2 = dynamic_cast<Dog*>(a2);
    if (d2) {
        d2->bark();
    }
    else {
        std::cout << "Failed to cast a Cat pointer to a Dog pointer." << std::endl;
    }

    return 0;
}
```

In this example, we have an `Animal` base class and two derived classes, `Dog` and `Cat`. We create a `Dog` object and a `Cat` object, both of which are accessed through `Animal` pointers. We then perform two `dynamic_cast` operations to convert the `Animal` pointers to `Dog` pointers. In the first case, the conversion succeeds, so we call the `bark()` method on the resulting `Dog` pointer. In the second case, the conversion fails, so we output an error message.

Note that `dynamic_cast` can only be used with pointers or references to classes that have at least one virtual function. This is because `dynamic_cast` works by checking the virtual function table of the object being pointed to, and non-polymorphic classes do not have virtual function tables.

Also, `dynamic_cast` can be a relatively expensive operation, as it involves run-time type checking. Therefore, it should be used judiciously and only when necessary.

## New C++ Style Casts

In C++, there are four new style casts that can be used to perform type conversions: `static_cast`, `dynamic_cast`, `reinterpret_cast`, and `const_cast`. These casts were introduced to replace the older C-style casts, which were less type-safe and could lead to undefined behavior.

Here's a brief description of each new style cast:

1. `static_cast`: This is a general-purpose cast that can be used to perform a wide range of type conversions, including implicit conversions between types, upcasts and downcasts in class hierarchies, and conversions to and from `void*`. It is similar to the older C-style cast, but is more type-safe and can catch more errors at compile time.
2. `dynamic_cast`: This is a run-time cast that can be used to safely convert pointers or references to classes up or down a class hierarchy. Unlike `static_cast`, `dynamic_cast` performs a run-time check to ensure that the conversion is valid and returns a null pointer if the conversion is not possible.
3. `reinterpret_cast`: This is a low-level cast that can be used to reinterpret the bit pattern of a pointer or reference as a different type. It can be used to perform unsafe type conversions, such as casting between unrelated types or casting away constness. It should be used with extreme care, as it can easily lead to undefined behavior.
4. `const_cast`: This is a cast that can be used to add or remove constness from pointers or references. It is often used to implement const-correctness in C++ code.

Here's an example that demonstrates the use of new style casts:

```cpp
#include <iostream>

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

class Dog : public Animal {
public:
    void bark() {
        std::cout << "Woof!" << std::endl;
    }
};

int main() {
    // static_cast example
    double d = 3.14;
    int i = static_cast<int>(d);
    std::cout << "d = " << d << ", i = " << i << std::endl;

    // dynamic_cast example
    Animal* a1 = new Dog();
    Animal* a2 = new Animal();
    Dog* d1 = dynamic_cast<Dog*>(a1);
    Dog* d2 = dynamic_cast<Dog*>(a2);
    if (d1) {
        d1->bark();
    }
    if (!d2) {
        std::cout << "a2 is not a Dog pointer." << std::endl;
    }

    // reinterpret_cast example
    int* p = new int(42);
    void* v = reinterpret_cast<void*>(p);
    int* q = reinterpret_cast<int*>(v);
    std::cout << "*q = " << *q << std::endl;

    // const_cast example
    const int ci = 42;
    const int* cp = &ci;
    int* ip = const_cast<int*>(cp);
    *ip = 43;
    std::cout << "ci = " << ci << ", *cp = " << *cp << ", *ip = " << *ip << std::endl;

    return 0;
}
```

In this example, we use each of the new style casts to perform a different type conversion. We use `static_cast` to convert a `double` to an `int`, `dynamic_cast` to convert `Animal` pointers to `Dog` pointers, `reinterpret_cast` to convert a pointer to an `int` to a `void*`, and `const_cast` to remove the constness of a pointer to an `int`. Each cast is used in a way that preserves type safety and avoids undefined behavior.

## Static Cast

In C++, `static_cast` is a type of cast that can be used to perform a wide range of type conversions, including implicit conversions between types, upcasts and downcasts in class hierarchies, and conversions to and from `void*`. It is similar to the older C-style cast, but is more type-safe and can catch more errors at compile time.

Here are some examples of how `static_cast` can be used:

1. Implicit conversions between types:

```cpp
int i = 42;
double d = static_cast<double>(i);
```

In this example, we use `static_cast` to convert an `int` to a `double`, which is an implicit conversion between types. This is a safe conversion that preserves the value of the original `int`.

2. Upcasts and downcasts in class hierarchies:

```cpp
class Animal {
public:
    virtual ~Animal() {}
};

class Dog : public Animal {
public:
    void bark() {
        std::cout << "Woof!" << std::endl;
    }
};

Animal* a = new Dog();
Dog* d = static_cast<Dog*>(a);
```

In this example, we have a `Dog` class that derives from an `Animal` class. We create a `Dog` object and obtain a pointer to it using a pointer to its base class, `Animal`. We then use `static_cast` to convert the `Animal` pointer to a `Dog` pointer, which is a downcast in the class hierarchy. This is a safe conversion because we know that the object being pointed to is actually a `Dog`.

3. Conversions to and from `void*`:

```cpp
int i = 42;
void* v = static_cast<void*>(&i);
int* p = static_cast<int*>(v);
```

In this example, we use `static_cast` to convert a pointer to an `int` to a `void*`, and then back to a pointer to an `int`. This is a safe conversion that preserves the value of the original pointer.

Note that `static_cast` can only be used for type conversions that are known to be safe at compile time. If you are not sure whether a conversion is safe, you should use a different type of cast, such as `dynamic_cast` or `reinterpret_cast`.

## Reinterpret Cast

In C++, `reinterpret_cast` is a type of cast that can be used to reinterpret the bit pattern of a pointer or reference as a different type. It can be used to perform unsafe type conversions, such as casting between unrelated types or casting away constness. It should be used with extreme care, as it can easily lead to undefined behavior.

Here are some examples of how `reinterpret_cast` can be used:

1. Casting between unrelated types:

```
int i = 42;
double* pd = reinterpret_cast<double*>(&i);
```

In this example, we use `reinterpret_cast` to cast a pointer to an `int` to a pointer to a `double`. This is a dangerous conversion that can lead to undefined behavior, as the bit pattern of an `int` and a `double` may be different. It should only be used in cases where you know that the memory being pointed to actually contains a `double`.

2. Casting away constness:

```cpp
const int ci = 42;
int* pi = const_cast<int*>(&ci);
```

In this example, we use `const_cast` to cast away the constness of a pointer to an `int`. This is a dangerous conversion that can lead to undefined behavior if the original object is actually const. It should only be used in cases where you know that the original object is not actually const.

3. Casting to and from `void*`:

```cpp
int i = 42;
void* pv = reinterpret_cast<void*>(&i);
int* pi = reinterpret_cast<int*>(pv);
```

In this example, we use `reinterpret_cast` to cast a pointer to an `int` to a `void*`, and then back to a pointer to an `int`. This is a safe conversion if the original pointer and the resulting pointer have the same type and address space.

Note that `reinterpret_cast` should be used with extreme care, as it can easily lead to undefined behavior. It should only be used in cases where you know that the memory being pointed to actually contains the type you're casting to, and that the resulting pointer will be used safely and correctly. In general, it's better to use a safer type of cast, such as `static_cast` or `dynamic_cast`, whenever possible.

## Const Cast

In C++, `const_cast` is a type of cast that can be used to add or remove constness from pointers or references. It is often used to implement const-correctness in C++ code.

Here are some examples of how `const_cast` can be used:

1. Casting away constness:

```cpp
const int ci = 42;
int* pi = const_cast<int*>(&ci);
```

In this example, we use `const_cast` to cast away the constness of a pointer to an `int`. This is useful when you need to modify the underlying variable, but it can be dangerous if the original object is actually const. It should only be used in cases where you know that the original object is not actually const.

2. Adding constness:

```cpp
int i = 42;
const int* p = const_cast<const int*>(&i);
```

In this example, we use `const_cast` to add constness to a pointer to an `int`. This is useful when you want to prevent the underlying variable from being modified, but it can be dangerous if the code that uses the pointer modifies the underlying variable anyway. It should only be used in cases where you know that the pointer will be used safely and correctly.

3. Removing volatile:

```cpp
volatile int vi = 42;
int* pi = const_cast<int*>(&vi);
```

In this example, we use `const_cast` to remove the `volatile` qualifier from a pointer to an `int`. This is useful when you need to modify the underlying variable, but it can be dangerous if the variable is actually volatile and the code that uses the pointer assumes that it is not. It should only be used in cases where you know that the variable is not actually volatile.

Note that `const_cast` should be used with care, as it can be dangerous if used incorrectly. In general, it's better to avoid casting away constness or other qualifiers whenever possible, and to use const-correctness to ensure that your code is safe and correct.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://adeshsingh.gitbook.io/programming/advanced-c++-programming/runtime-type-information.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
