Recently I noticed my knowledge about C++ cast operators had been far from complete. For instance, I had thought static_cast is only for static upcasts(or downcasts also?) in an inheritance hierarchy. And for some legitimate casts between primitive types(like between int and float or between int and unsigned int), I used the C-style cast, still. I was not sure about how new cast operators are precisely mapped to the old C-style, either. So here is my shot at finally clarifying all these.

Categories

Errors possible
  • Es : compile error
  • Er: run-time check failure
    • an exception when casting a reference
    • returing nullptr when casting a pointer
  • Ec : run-time crash when using the converted
Conversions supported
  • Cprim: between primitive types : int <-> float, int <-> unsigned int
    • built-in conversion rules apply
  • pointer(reference) types
    • Cbase: pointer to a linearly related type(upcast/downcast) : CDerived* <-> CBased*
      • a proper pointer arithmetic applies if a multiple inheritance used
    • Cvoid : void pointer : void* <-> int*
    • Cconst : removing const/volatile type qualifiers : const int* <-> int*
    • Cetc : Any other cases : int* <-> float*

Casts

static_cast<>
  • Cprim, Cbase, Cvoid
  • Es if Cconst, Cetc tried
  • A possible Ec if an invalid downcast tried e.g. CBase* pB = new CBase(); CDerived* pD = static_cast<CDerived*>(pB);
reinterpret_cast<>
  • Cbase, Cvoid, Cetc
  • Es if Cprim, Cconst tried
  • A possible Ec if Cbase tried(because a proper point arithmetic isn’t applied)
dynamic_cast<>
  • Cbase, dynamic_cast<void*>
    • The latter returns a pointer to the complete(i.e. most-dervied) object.
  • Es if Cprim, Cvoid, Cconst, Cetc
  • A possible Er if a downcast of Cbase tried and its run-time check fails
const_cast<>
  • Cconst
  • Es if Cprim, Cbase, Cvoid, Cetc
C-style cast
  • A C-style cast is defined as the first of the following which succeeds:
    • const_cast
    • static_cast
    • static_cast, then const_cast
    • reinterpret_cast
    • reinterpret_cast, then const_cast

Conclusion

  • Never use the C-style cast any more. You can use one among (or an combo of) const_cast, static_cast, reinterpret_cast depending on your exact need at that time.
  • dynamic_cast is a complete new thing in C++ and use it sparingly since it has a run-time cost and a need for it might be a symptom of some bad underlying design(though this aspect of it has not been discussed in this article).
  • C++ is too deep (for a mere mortal to figure all its nooks and crannies).

References

(This article has also been posted to my personal blog.)

Update – dynamic_cast<void*> and the fourth reference added