Type Casting (static_cast & more)

Sometimes a value is the wrong type and you need to convert it deliberately. C++ gives you four named casts — static_cast , dynamic_cast , const_cast , and reinterpret_cast — each with a clear purpose. This lesson teaches you which to reach for, why they beat C-style (int) casts, and the truncation traps to watch for.

Learn Type Casting (static_cast & more) in our free C++ course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…

Part of the free C++ course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Think of the four casts as four different adapters . static_cast is a sensible travel adapter — it connects compatible plugs (an int into a double socket). dynamic_cast is a security guard who checks ID at the door and turns you away if you're not really who you claim to be. const_cast is a master key that removes a "do not touch" sticker — powerful but easy to misuse. reinterpret_cast is a crowbar that forces two unrelated things together by brute reinterpretation of their bits. You reach for the gentlest tool that does the job — almost always static_cast .

1. static_cast : the workhorse

This is the cast you'll use 95% of the time. It converts between related types: int ↔ double , char ↔ its numeric code, and pointers within a hierarchy. The classic use is breaking the integer-division trap by casting one operand to double .

2. Truncation vs Rounding

Casting a double to int truncates toward zero — it chops the fraction, it does not round. If you want the nearest whole number, round first with std::round (or use std::lround , which returns an integer directly).

3. dynamic_cast : safe downcasting

When you have a base-class pointer and need to know the real derived type, dynamic_cast checks at runtime. It returns nullptr for pointers (or throws std::bad_cast for references) when the object isn't the type you asked for. It requires the base class to be polymorphic — at least one virtual function.

4. const_cast : removing const (carefully)

const_cast adds or removes const . Its main legitimate use is calling an older API that forgot to mark a read-only parameter const . Never use it to actually modify an object that is genuinely const — that's undefined behavior.

5. reinterpret_cast : raw bits (last resort)

This is the most dangerous cast. It views the same bytes through a completely different type — useful for low-level work like inspecting a value's individual bytes or treating a pointer as an integer address, but non-portable and easy to misuse. Reach for it only when nothing else works.

Your turn. Cast one operand so the percentage keeps its decimals:

These lines round a price to the nearest cent-free whole number and print it. Reorder so the program prints 4 .

Why: must precede any use of round . Inside main , declare price first, then round(3.6) gives 4.0 and static_cast<int> converts that cleanly to 4 (rounding before casting avoids truncating 3.6 down to 3 ). Then print and close the function.

Predict the output before revealing each answer.

2 — casting a double to int truncates toward zero; it does not round to 3.

a — 97 is the ASCII code for lowercase 'a', so casting the int to char prints that character.

2.5 — casting one operand to double makes the whole division floating-point.

Read points earned and possible, compute a rounded percentage with a cast, and map it to a letter grade. Match the expected output in the comments.

Practice quiz

What does static_cast<int>(3.9) evaluate to?

  • 4
  • 3.9
  • 3
  • 0

Answer: 3. Converting a double to int truncates toward zero — it drops the fraction rather than rounding, so 3.9 becomes 3.

What does static_cast<int>(-3.9) evaluate to?

  • -3
  • -4
  • -3.9
  • 3

Answer: -3. Truncation is toward zero, not toward negative infinity, so -3.9 becomes -3 (not -4).

Which cast should you reach for 95% of the time, for related numeric and char conversions?

  • reinterpret_cast
  • const_cast
  • dynamic_cast
  • static_cast

Answer: static_cast. static_cast handles well-defined, related conversions and is checked at compile time. It is the everyday workhorse cast.

Which cast is used for safe downcasting in a class hierarchy, checked at runtime?

  • static_cast
  • dynamic_cast
  • const_cast
  • reinterpret_cast

Answer: dynamic_cast. dynamic_cast checks the real type at runtime, returning nullptr for pointers (or throwing std::bad_cast for references) on failure.

What does dynamic_cast require of the base class to work?

  • At least one virtual function (polymorphic)
  • A copy constructor
  • A const destructor
  • Template parameters

Answer: At least one virtual function (polymorphic). dynamic_cast needs the base class to be polymorphic — at least one virtual function (commonly a virtual destructor).

What does static_cast<double>(7) / 2 evaluate to?

  • 3
  • 3.0
  • 3.5
  • 4

Answer: 3.5. Casting one operand to double makes the division floating-point: 7.0 / 2 = 3.5.

What does static_cast<double>(7 / 2) evaluate to?

  • 3.5
  • 3.0
  • 4.0
  • 2

Answer: 3.0. The integer division 7 / 2 happens first and truncates to 3; casting that to double gives 3.0. Cast an operand, not the result.

What does static_cast<char>(97) print?

  • 97
  • 9
  • A
  • a

Answer: a. 97 is the ASCII code for lowercase 'a', so casting the int to char yields that character.

What is the main legitimate use of const_cast?

  • Speeding up loops
  • Calling a legacy API that forgot to mark a parameter const
  • Converting double to int
  • Downcasting pointers

Answer: Calling a legacy API that forgot to mark a parameter const. const_cast strips const to satisfy older non-const APIs. Actually modifying a genuinely const object through it is undefined behavior.

Why prefer named C++ casts over a C-style cast like (int)x?

  • They are shorter to type
  • They run faster at runtime
  • They make intent explicit and let the compiler reject nonsense
  • They are required by the standard

Answer: They make intent explicit and let the compiler reject nonsense. A C-style cast silently tries const_cast, static_cast, even reinterpret_cast. Named casts state intent, are searchable, and reject invalid conversions.