Sobes.tech
Junior

Name the type casting operators in C++.

sobes.tech AI

Answer from AI

In C++, the following type cast operators are used:

  • static_cast: Performs conversions between related types where the compiler can verify correctness. For example, between numeric types, from a pointer to a base class to a pointer to a derived class (without virtual functions), and vice versa, between pointers and void*. It is unsafe for conversions from Derived* to Base* if there are no guarantees that the pointer actually points to a Derived object.
  • dynamic_cast: Used for safe casting of pointers and references within class hierarchies with virtual functions. Type checking is performed at runtime. If the cast is impossible, it returns nullptr for pointers or throws a std::bad_cast exception for references. It requires the type to be polymorphic (have virtual functions).
  • const_cast: Used to modify (remove or add) const and volatile qualifiers. Using it to remove const from an object originally declared as const and then modifying it leads to undefined behavior.
  • reinterpret_cast: Performs low-level, least safe conversions. It allows converting one pointer type to another, a pointer to an integer, and vice versa, without any checks. The result depends on the implementation and may be non-portable. It is typically used for interacting with low-level APIs or hardware.

Example usage:

#include <iostream>
#include <vector>

class Base {
public:
    virtual ~Base() = default; // Virtual destructor for dynamic_cast
    void baseMethod() { std::cout << "Base method\n"; }
};

class Derived : public Base {
public:
    void derivedMethod() { std::cout << "Derived method\n"; }
};

int main() {
    double d = 3.14;
    int i = static_cast<int>(d); // static_cast: double to int

    Base* basePtr = new Derived();
    Derived* derivedPtr = dynamic_cast<Derived*>(basePtr); // dynamic_cast: Base* to Derived*

    if (derivedPtr) {
        derivedPtr->derivedMethod();
    } else {
        std::cout << "dynamic_cast failed\n";
    }

    const int constVal = 10;
    int* nonConstPtr = const_cast<int*>(&constVal); // const_cast: const int* to int*
    // *nonConstPtr = 20; // Undefined behavior if constVal was originally declared as const

    unsigned long address = reinterpret_cast<unsigned long>(basePtr); // reinterpret_cast: pointer to integer

    std::cout << "static_cast result: " << i << std::endl;
    std::cout << "reinterpret_cast result: " << address << std::endl;

    delete basePtr;
    return 0;
}