Instagram
youtube
Facebook
Twitter

Type Casting

Type Casting:

Type casting in C++ is the process of converting one data type into another. It allows you to explicitly change the interpretation or representation of a value to perform type casting in C++.

  • C-style Cast: The traditional ‘C-style cast’ can be used to perform colourful types of conversions. It isn’t recommended in C++ because it performs implicit conversions and might lead to unintended consequences.
#include <iostream>

int main() {

    double pi = 3.14159;

    int approximatePi = (int)pi;

    std::cout << "Approximate Pi (int): " << approximatePi << std::endl;

    const int constValue = 42;

    int* nonConstPtr = (int*)&constValue;

    *nonConstPtr = 100;

    std::cout << "Non-const Value: " << *nonConstPtr << std::endl;        return 0;

}

 

  • Static Cast: The static cast is a safer alternative to the C-style cast. It allows most of the standard conversions and conversions that do not involve pointers to unconnected types.
#include <iostream>

int main() {

    double pi = 3.14159;

    int approximatePi = static_cast<int>(pi);

    std::cout << "Approximate Pi (int): " << approximatePi << std::endl;

    class Base {};

    class Derived : public Base {};

    Base* basePtr = new Derived;

    Derived* derivedPtr = static_cast<Derived*>(basePtr);

    delete derivedPtr;

    return 0;

}

 

  • Dynamic Cast: The term dynamic_cast is used in the context of inheritance and polymorphism. It’s primarily used for converting pointers or references to base classes to pointers or references to derived classes.
#include <iostream>

class Shape {

public:

    virtual void print() { std::cout << "Shape" << std::endl; }

    virtual ~Shape() {}

};

class Circle : public Shape {

public:

    void print() override { std::cout << "Circle" << std::endl; }

};

class Triangle : public Shape {

public:

    void print() override { std::cout << "Triangle" << std::endl; }

};

int main() {

    Shape* shapePtr = new Circle;

    if (Circle* circlePtr = dynamic_cast<Circle*>(shapePtr)) {

        circlePtr->print();

    } else if (Triangle* trianglePtr = dynamic_cast<Triangle*>(shapePtr)) {

        trianglePtr->print();

    } else {

        shapePtr->print();

    }

delete shapePtr;

 return 0;

}

 

  • Reinterpret Cast: The reinterpret_cast performs low-level reinterpretations of bits. It’s used for converting one pointer type to another unconnected pointer type, converting pointers to integral types, and vice versa. It should be used with caution, as it can lead to undetermined behaviour if misused.

 

int num = 10;

char* charPtr = reinterpret_cast<char*>(&num);

 

  • Const Cast: The ‘const_cast’ is used to add or remove the ‘const’ qualifier from a variable. It’s substantially used to modify const variables, which otherwise would be illegal.
#include <iostream>

int main() {

    int intValue = 42;

    char* charPtr = reinterpret_cast<char*>(&intValue);

    for (size_t i = 0; i < sizeof(int); ++i) {

             std::cout << "Byte " << i << ": " << static_cast<int>(charPtr[i]) << std::endl;

    }

    int* intPtr = reinterpret_cast<int*>(charPtr);

    std::cout << "Value using int pointer: " << *intPtr << std::endl;

    return 0;

}

 

  • Functional Cast Notation: C++11 introduced the functional cast notation using angle brackets (‘<>’). This is equivalent to using ‘static_cast’.
#include <iostream>

class Base {

public:

    virtual ~Base() {}

};

class Derived : public Base {};

int main() {

    double pi = 3.14159;

    int approximatePi = int(pi);

    std::cout << "Approximate Pi (int): " << approximatePi << std::endl;


    Base* basePtr = new Derived;

    Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);

    if (derivedPtr) {

        std::cout << "Dynamic Cast: Successful" << std::endl;

    } else {

        std::cout << "Dynamic Cast: Failed" << std::endl;

    }

    const int constValue = 42;

    int nonConstValue = const_cast<int&>(constValue);

    nonConstValue = 100;

    std::cout << "Non-const Value: " << nonConstValue << std::endl;

    int intValue = 123456789;

    char* charPtr = reinterpret_cast<char*>(&intValue);

    std::cout << "First byte of int: " << static_cast<int>(*charPtr) << std::endl;

    delete basePtr;

    return 0;

}

 

When performing typecasting, it’s essential to ensure that the conversion is valid and meaningful. Indecorous typecasting can lead to data loss, undetermined behaviour, or runtime errors. Use type casting judiciously and prefer safer alternatives like ‘static_cast’ or ‘dynamic_cast’ when appropriate.