|
| 1 | +--- |
| 2 | +Title: "C++: static_cast, dynamic_cast, reinterpret_cast, and const_cast" |
| 3 | +layout: post |
| 4 | +title: "C++: static_cast, dynamic_cast, reinterpret_cast, and const_cast" |
| 5 | +--- |
| 6 | +In C++, the four cast operators (`static_cast`, `dynamic_cast`, `reinterpret_cast`, and `const_cast`) are used for different types of type conversions. Here’s an explanation of each, along with examples. |
| 7 | + |
| 8 | +### 1. `static_cast` |
| 9 | +`static_cast` is used for most type conversions that are known to be valid at compile time. For example, it can be used to convert a pointer from a base class to a derived class or convert primitive data types. |
| 10 | + |
| 11 | +**Example:** |
| 12 | +```cpp |
| 13 | +#include <iostream> |
| 14 | + |
| 15 | +class Base { |
| 16 | +public: |
| 17 | + virtual void print() { |
| 18 | + std::cout << "Base class" << std::endl; |
| 19 | + } |
| 20 | +}; |
| 21 | + |
| 22 | +class Derived : public Base { |
| 23 | +public: |
| 24 | + void print() override { |
| 25 | + std::cout << "Derived class" << std::endl; |
| 26 | + } |
| 27 | +}; |
| 28 | + |
| 29 | +int main() { |
| 30 | + Base* basePtr = new Derived(); |
| 31 | + |
| 32 | + // Use static_cast to convert base class pointer to derived class pointer |
| 33 | + Derived* derivedPtr = static_cast<Derived*>(basePtr); |
| 34 | + derivedPtr->print(); // Outputs "Derived class" |
| 35 | + |
| 36 | + // Conversion between primitive data types |
| 37 | + int a = 10; |
| 38 | + double b = static_cast<double>(a); |
| 39 | + std::cout << "b = " << b << std::endl; // Outputs "b = 10.0" |
| 40 | + |
| 41 | + delete basePtr; |
| 42 | + return 0; |
| 43 | +} |
| 44 | +``` |
| 45 | +
|
| 46 | +### 2. `dynamic_cast` |
| 47 | +`dynamic_cast` is used for type conversions that are checked at runtime. It is primarily used with polymorphic classes (i.e., classes that have at least one virtual function). If the conversion is not valid, `dynamic_cast` returns `nullptr` for pointer conversions. |
| 48 | +
|
| 49 | +**Example:** |
| 50 | +```cpp |
| 51 | +#include <iostream> |
| 52 | +
|
| 53 | +class Base { |
| 54 | +public: |
| 55 | + virtual void print() { |
| 56 | + std::cout << "Base class" << std::endl; |
| 57 | + } |
| 58 | +}; |
| 59 | +
|
| 60 | +class Derived : public Base { |
| 61 | +public: |
| 62 | + void print() override { |
| 63 | + std::cout << "Derived class" << std::endl; |
| 64 | + } |
| 65 | +}; |
| 66 | +
|
| 67 | +int main() { |
| 68 | + Base* basePtr = new Derived(); |
| 69 | + |
| 70 | + // Use dynamic_cast to convert base class pointer to derived class pointer |
| 71 | + Derived* derivedPtr = dynamic_cast<Derived*>(basePtr); |
| 72 | + |
| 73 | + if (derivedPtr) { |
| 74 | + derivedPtr->print(); // Outputs "Derived class" |
| 75 | + } else { |
| 76 | + std::cout << "Conversion failed!" << std::endl; |
| 77 | + } |
| 78 | + |
| 79 | + Base* baseOnly = new Base(); |
| 80 | + Derived* invalidPtr = dynamic_cast<Derived*>(baseOnly); |
| 81 | + |
| 82 | + if (invalidPtr) { |
| 83 | + invalidPtr->print(); |
| 84 | + } else { |
| 85 | + std::cout << "Conversion failed!" << std::endl; // Outputs this |
| 86 | + } |
| 87 | +
|
| 88 | + delete basePtr; |
| 89 | + delete baseOnly; |
| 90 | + return 0; |
| 91 | +} |
| 92 | +``` |
| 93 | + |
| 94 | +### 3. `reinterpret_cast` |
| 95 | +`reinterpret_cast` performs a low-level, bitwise conversion. It can be used to convert pointers to integers and vice versa. This cast should be used cautiously, as incorrect use can lead to undefined behavior. |
| 96 | + |
| 97 | +**Example:** |
| 98 | +```cpp |
| 99 | +#include <iostream> |
| 100 | + |
| 101 | +int main() { |
| 102 | + int num = 42; |
| 103 | + |
| 104 | + // Convert a pointer to an integer and back |
| 105 | + int* ptr = # |
| 106 | + uintptr_t intPtr = reinterpret_cast<uintptr_t>(ptr); |
| 107 | + std::cout << "Integer pointer: " << intPtr << std::endl; |
| 108 | + |
| 109 | + int* newPtr = reinterpret_cast<int*>(intPtr); |
| 110 | + std::cout << "Value at pointer: " << *newPtr << std::endl; // Outputs "42" |
| 111 | + |
| 112 | + return 0; |
| 113 | +} |
| 114 | +``` |
| 115 | + |
| 116 | +### 4. `const_cast` |
| 117 | +`const_cast` is used to remove the `const` or `volatile` qualifier from a variable. This is useful if you need to modify a variable that was originally declared as `const`. However, changing a value that was originally declared as `const` can lead to undefined behavior. |
| 118 | + |
| 119 | +**Example:** |
| 120 | +```cpp |
| 121 | +#include <iostream> |
| 122 | + |
| 123 | +void printValue(const int* value) { |
| 124 | + // Remove the const qualifier |
| 125 | + int* modifiableValue = const_cast<int*>(value); |
| 126 | + *modifiableValue = 100; |
| 127 | +} |
| 128 | + |
| 129 | +int main() { |
| 130 | + int num = 42; |
| 131 | + printValue(&num); |
| 132 | + std::cout << "New value: " << num << std::endl; // Outputs "New value: 100" |
| 133 | + |
| 134 | + return 0; |
| 135 | +} |
| 136 | +``` |
| 137 | +
|
| 138 | +### Summary |
| 139 | +- **`static_cast`:** Compile-time conversion, e.g., base class to derived class, primitive data types. |
| 140 | +- **`dynamic_cast`:** Runtime-checked conversion, used with polymorphic classes, safely converts base class to derived class. |
| 141 | +- **`reinterpret_cast`:** Unsafe bit-level conversion, e.g., between pointers and integers. |
| 142 | +- **`const_cast`:** Removes `const` or `volatile` qualifiers, allows modification of `const` declared variables. |
0 commit comments