CodeRef
CodeRef
  • Software
    • VSCode
  • Midjourney_AI
    • Midjourney Cheat Sheet
  • aws
    • S3 Reference
    • Services
  • bash
    • .bashrc File Contents
    • CAN
    • _System Config File Locations
    • argument-length-limits
    • Conditionals
    • Data Structures
    • File Permissions
    • File Syncing
    • File System
    • Functions
    • General
    • Loops
    • My Functions
    • Networking
    • Number Operations
    • OpenVPN
    • Operators
    • Resource Management
    • Serial RS232
    • Spinning Wheel Animation
    • SSH
    • Text Operations
    • Environment Variables
  • cpp
    • ChatGPT | Pointers vs. References
    • arrays
    • Classes
    • Data Types / Structures
    • Enumerated Classes
    • Exception Handling
    • Function Objects
    • Functions
    • I/O
    • Loops
    • Macros
    • Namespaces
    • New Features
    • Pointers
    • Scope
    • Smart Pointers
    • Raw String Literals
    • Style Guide
    • Switch Case
    • Templating
    • How to Use tinyxml2
    • Useful Libraries
    • google-test
    • Conditionals
    • Rule of Three/Five
    • Optional Parameters
    • Keywords
    • Filesystem
    • Random
    • Casting
    • tools
  • git
    • Code Review Dependency Strategy
    • Git Bisect Guide
    • Git Reference
    • removing-cherry-picks
    • Useful Tools
    • Graphite Reference
  • js
    • functions
    • Javascript Reference
  • linux
    • Display
    • Dual Boot with Windows
    • File System
    • NVIDIA
    • Sending/Receiving TCP/UDP Messages in Ubuntu
    • dynamically_linked_binaries
  • markdown
    • Images
    • obsidian-reference
  • python
    • Classes
    • Exceptions
    • Functions
    • Operations
    • Python Reference
    • unittest_command-line-args
    • unittest_magicmock_GPT
    • unittest_mock
    • unittest_printing
    • unittest_subtest
    • useful-stuff
    • jupyter
    • poetry
  • ros
    • _ROS Cheat Sheet
    • Create New Workspace
    • Install ROS
    • Node Sample - Listener
    • Node Sample - Talker
    • Node Template
    • Setup
    • urdf
  • excel
    • excel-reference
  • windows
    • File System
    • WSL - Windows Subsystem for Linux
    • WSL
  • software_engineering
    • uncle_bob_lectures
      • Overview
      • Lesson 01 - Notes
  • web
    • Front End
    • Hugo
    • new_frontend_tools
  • sql
    • cheatsheet
Powered by GitBook
On this page
  • C++ Special Casts Explained
  • 1. static_cast
  • 2. dynamic_cast
  • 3. const_cast
  • 4. reinterpret_cast
  • Best Practices
  1. cpp

Casting

From Claude 3.5 Sonnet.

C++ Special Casts Explained

C++ provides several special cast operators to handle different types of type conversions safely and explicitly. These casts are:

  1. static_cast

  2. dynamic_cast

  3. const_cast

  4. reinterpret_cast

Let's explore each of these in detail.

1. static_cast

static_cast is used for conversions between related types, such as numeric types or up and down a class hierarchy.

Usage:

static_cast<new_type>(expression)

Examples:

// Convert int to float
int i = 10;
float f = static_cast<float>(i);

// Upcast (derived class to base class)
class Base {};
class Derived : public Base {};
Derived d;
Base* b = static_cast<Base*>(&d);

// Downcast (base class to derived class) - unsafe, use dynamic_cast for this
Base* b = new Derived();
Derived* d = static_cast<Derived*>(b); // This works but can be dangerous

2. dynamic_cast

dynamic_cast is used for safe downcasting in inheritance hierarchies. It performs a runtime check and returns nullptr (for pointers) or throws an exception (for references) if the cast is not valid.

Usage:

dynamic_cast<new_type>(expression)

Example:

class Base { virtual void dummy() {} };  // Must have at least one virtual function
class Derived : public Base { };

Base* b1 = new Base();
Base* b2 = new Derived();

Derived* d1 = dynamic_cast<Derived*>(b1);  // Returns nullptr
Derived* d2 = dynamic_cast<Derived*>(b2);  // Returns valid pointer

if (d1) {
    std::cout << "Cast successful" << std::endl;
} else {
    std::cout << "Cast failed" << std::endl;
}

3. const_cast

const_cast is used to add or remove const (or volatile) qualifiers from a variable.

Usage:

const_cast<new_type>(expression)

Example:

const int* ptr = new int(10);
int* mutable_ptr = const_cast<int*>(ptr);
*mutable_ptr = 20;  // Modifies the original data

// Note: Modifying a value that was originally declared const 
// leads to undefined behavior

4. reinterpret_cast

reinterpret_cast is used for low-level reinterpreting of bit patterns. It's the most dangerous cast and should be used sparingly.

Usage:

reinterpret_cast<new_type>(expression)

Example:

int* p = new int(42);
char* ch = reinterpret_cast<char*>(p);

std::cout << *p << std::endl;  // Prints 42
std::cout << *ch << std::endl; // Undefined behavior

// Convert between unrelated pointer types
uintptr_t addr = reinterpret_cast<uintptr_t>(p);
int* p2 = reinterpret_cast<int*>(addr);

Best Practices

  1. Use static_cast for most conversions between related types.

  2. Use dynamic_cast for safe downcasting in polymorphic class hierarchies.

  3. Use const_cast only when you're certain that the original variable wasn't const.

  4. Use reinterpret_cast only in low-level code where you need to reinterpret memory.

  5. Avoid C-style casts (new_type)expression as they can hide dangerous conversions.

Remember, explicit casts should be used judiciously. If you find yourself using many casts, especially reinterpret_cast or const_cast, it might indicate a design problem in your code.

Last updated 9 months ago