Difference Between static_cast and dynamic_cast in C++

In C++, static_cast and dynamic_cast are type-casting operators designed to handle conversions between different data types, but they operate under fundamentally different mechanisms and safety guarantees. The core functional difference lies in when the cast is evaluated: static_cast resolves conversions at compile time without runtime safety checks, whereas dynamic_cast relies on Run-Time Type Information (RTTI) to verify conversions during program execution, specifically within polymorphic inheritance hierarchies.

Evaluation Time and Overhead

  • static_cast: Executes entirely at compile time. It generates direct conversion logic with zero runtime performance cost. Because the compiler enforces the validity of the cast based purely on static type rules, it cannot verify the actual underlying object being pointed to at runtime.
  • dynamic_cast: Executes primarily at runtime. It inspects the object’s runtime metadata via RTTI to verify whether the target type is valid. This process involves traversing the class hierarchy, introducing a minor runtime performance overhead.

Safety and Downcasting

Downcasting refers to casting a pointer or reference of a base class to a derived class.

  • static_cast: Permits downcasting, but it is inherently unsafe. If a base pointer does not actually point to an instance of the derived class, static_cast still succeeds, yielding a dangling or invalid pointer. Calling derived-class methods on this pointer results in undefined behavior.
  • dynamic_cast: Guarantees safe downcasting. It checks whether the underlying object matches the target type:
    • When casting pointers, it returns nullptr if the cast fails.
    • When casting references, it throws a std::bad_cast exception if the cast fails (since null references cannot exist in C++).

Requirement for Polymorphism

  • static_cast: Does not require polymorphism. It can convert between non-polymorphic classes, numeric types (e.g., double to int), void* to concrete pointers, and non-virtual class hierarchies.
  • dynamic_cast: Requires the base class to be polymorphic (i.e., contain at least one virtual function) when downcasting or cross-casting. If you attempt to use dynamic_cast to downcast a non-polymorphic base class, the compiler generates an error.

Cross-Casting and Multiple Inheritance

In complex class hierarchies involving multiple inheritance or diamond inheritance, dynamic_cast can perform cross-casting—navigating horizontally across the inheritance tree from one sibling base class to another. static_cast cannot resolve cross-casts because compile-time checks lack the layout information provided by the runtime vtable.

Summary of Use Cases

  • Use static_cast for standard conversions (such as basic data types, void* conversions, or upcasting) and for downcasting only when you are absolutely certain of the dynamic type and performance is critical.
  • Use dynamic_cast whenever downcasting or cross-casting within polymorphic class hierarchies where the actual runtime type of the object is uncertain.