Type casting is the process of converting a value from one data type to another. In C, it is performed explicitly by the programmer using the cast operator.
- Used to convert incompatible data types when required during expressions or assignments.
- Helps control the conversion process and prevents unintended loss of data in calculations.
#include <bits/stdc++.h>
using namespace std;
int main() {
char c = 'a';
// Converting c from char to int
int i = static_cast<int>(c);
// Printing the converted value
cout << i;
return 0;
}
Output
97
Explanation: Type casting allows programmers to convert data into the required type whenever automatic conversion is not suitable. C++ provides four specialized cast operators that are safer and more expressive than traditional C-style casts.
Types of casting
C++ provides four different casting operators, each designed for a specific type conversion.
Static_cast
The static_cast is used to perform compile-time type conversion between compatible data types and is considered safe by the compiler.
- It is mainly used for explicit conversions between compatible primitive and user-defined types.
- It performs compile-time checking, making conversions more readable and safer than C-style casts.
Syntax
static_cast <new_type> (exp);
where,
- exp: Data to be converted.
- new_type: Desired type of expression
The static_cast can be used to convert between related types, such as numeric types or pointers in the same inheritance hierarchy.
#include <bits/stdc++.h>
using namespace std;
int main() {
int n = 10;
// converting int to double
double nd = static_cast<double>(n);
// printing data type
cout << typeid(n).name() << endl;
// typecasting
cout << typeid(static_cast<double>(n)).name() << endl;
// Printing double type
cout << typeid(nd).name();
return 0;
}
Output
i d d
Explanation
In the above example, typeid() is used to verify the data type before and after performing static_cast.
- An int variable is converted into a double using static_cast.
- typeid() is used to display the data types of the original and converted values.
- The output i, d, d indicates that the original type is int and the converted value is of type double.
Dynamic_cast
The dynamic_cast is used to safely perform downcasting between base and derived classes in polymorphic class hierarchies.
- It performs runtime type checking to ensure the conversion is valid.
- If the cast is invalid, it returns nullptr for pointers (or throws an exception for references).
Syntax
dynamic_cast <new_type> (exp);
If the conversion is not possible, dynamic_cast returns a null pointer (for pointer conversions) or throws a bad_cast exception (for reference conversions).
#include <iostream>
using namespace std;
// Base Class
class Animal {
public:
virtual void speak() {
cout << "Animal speaks." << endl;
}
};
// Derived Class
class Dog : public Animal {
public:
void speak() override {
cout << "Dog barks." << endl;
}
};
// Derived Class
class Cat : public Animal {
public:
void speak() override {
cout << "Cat meows." << endl;
}
};
int main() {
// Base class pointer to derived class object
Animal* animalPtr = new Dog();
// Downcasting
Dog* dogPtr = dynamic_cast<Dog*>(animalPtr);
// Checking if the typecasting is successfull
if (dogPtr) {
dogPtr->speak();
}
else {
cout << "Failed to cast to Dog." << endl;
}
// Typecasting to other dervied class
Cat* catPtr = dynamic_cast<Cat*>(animalPtr);
if (catPtr) {
catPtr->speak();
}
else {
cout << "Failed to cast to Cat." << endl;
}
delete animalPtr;
return 0;
}
Output
Dog barks. Failed to cast to Cat.
Explanation
In the above example, dynamic_cast successfully converts the base class pointer to the correct derived class, while an invalid cast fails safely.
- The cast from Animal* to Dog* succeeds because the pointer refers to a Dog object.
- The cast from Animal* to Cat* fails since the object is not of type Cat.
- dynamic_cast ensures type safety by returning nullptr when the cast is invalid.
const_cast
The const_cast is used to add or remove the const or volatile qualifier from a variable or pointer.
- It allows modification of a non-const object that is accessed through a const pointer or reference.
- Modifying an object that was originally declared as const results in undefined behavior.
Syntax
const_cast <new_type> (exp);
#include <iostream>
using namespace std;
int main() {
const int n = 5;
// Pointer to a const int
const int* ptr = &n;
// int* nonConstPtr = ptr; if we use this
// instead of without using const_cast
// we will get error of invalid conversion
int* nonConstPtr = const_cast<int*>(ptr);
*nonConstPtr = 10;
cout << *nonConstPtr;
return 0;
}
Output
10
Explanation
In the above example, a const pointer is type cast to a non-const pointer to modify the stored value.
- A const pointer is converted into a non-const pointer using explicit type casting.
- The value is modified through the non-const pointer.
- The updated value is then printed to verify the modification.
Reinterpret_cast
The reinterpret_cast is used to convert one pointer type into another unrelated pointer type.
- It performs no compile-time or runtime type checking during the conversion.
- It is mainly used for low-level memory manipulation and should be used with caution.
Syntax
reinterpret_cast <new_type> (exp);
#include <iostream>
using namespace std;
int main() {
int n = 10;
// Store the address of number in nptr
int* nptr = &n;
// Reinterpreting the pointer as a char pointer
char* charptr = reinterpret_cast<char*>(nptr);
// Printing the memory addresses and values
printf("Integer Address: %p\n", nptr);
printf("Char Address: %p", charptr);
return 0;
}
Output
Integer Address: 0x7ffca2a2980c Char Address: 0x7ffca2a2980c
Explanation
In the above example, an int pointer is explicitly type cast to a char pointer using the cast operator.
- An int variable is created, and its address is stored in an int pointer.
- The int pointer is converted into a char pointer using explicit type casting.
- Printing both pointer addresses shows that only the pointer type changes, not the actual memory address.