views:

24329

answers:

6

I am reasonably proficient in C++, but I do not have a lot of experience using the cast operators to convert pointers of one type to another. I am familiar with the risks and benefits of pointer casting, as well as the evils of using C-style casts. What I am looking for is a primer on the proper ways to use the various cast operators in C++.

What are the proper uses of static_cast, dynamic_cast and reinterpret_cast, and how does one decide which one to use in a specific case?

+4  A: 

Does this answer your question?

I have never used reinterpret_cast, and wonder whether running into a case that needs it isn't a smell of bad design. In the code base I work on dynamic_casts are used a lot. The difference with static_cast is that a dynamic_cast does runtime checking which may (safer) or may not (more overhead) be what you want (see msdn).

andreas buykx
I have used reintrepret_cast for one purpose -- getting the bits out of a double (same size as long long on my platform).
Joshua
+7  A: 

Use dynamic_cast for converting pointers/references within an inheritance hierarchy.

Use static_cast for ordinary type conversions.

Use reinterpret_cast for low-level reinterpreting of bit patterns. Use with extreme caution.

Use const_cast for casting away const/volatile. Avoid this unless you are stuck using a const-incorrect API.

Fred Larson
const correctness makes me spit at the sight of it.
Kieveli
const correctness is one of the C++ programmer's best tools. It keeps you from making stupid errors.
coppro
Agreed. I spit at the sight of developers who don't understand const correctness and why it is a good thing.
+31  A: 

static_cast

  • It is able to do the reverse of what an implicit conversion can do. Meaning: narrow (long -> int), widen (int -> long), base-to-derived, void*-to-T* for example. You can't use it for the stuff that an reversed implicit conversion cannot do. (I.e you cannot cast an int* into int).

dynamic_cast

  • It is used to cast a base pointer into a derived pointer. If the base pointer doesn't point to an object of the type of the derived, it returns 0.
  • It is used to cast a base reference into a derived reference. If the reference isn't pointing to an object of the derived, it throws std::bad_cast.
  • It can be considered the checked cast equivalent to static_cast, in that it checks whether the object pointed to really is of the derived type.

reinterpret_cast

  • It is used to cast a pointer type to a wide enough integral type and back to the original pointer type.
  • It is used to cast between pointer types of incompatible types (int* to double* for example). The result of that mapping is unspecified, but it's possible to do so.

const_cast

  • It is used to cast away const or volatile. It is used in the rare cases when you have a originally non-const object, which is pointed to by a pointer-to-const or referenced to by a reference-to-const. Casting away constness is considered evil and should not be done if it can be avoided.

A C-style cast is equivalent to the following C++ style casts. The first cast that succeeds is taken (See 5.4 in the Standard):

const_cast, static_cast, static_cast followed by const_cast, reinterpret_cast, reinterpret_cast followed by const_cast.

Johannes Schaub - litb
Beautiful answer, litb. It is a close call between yours and coppro's. Thank you!
e.James
thanks eJames. i forgot to mention some important things though, which coppro thought about. so you did actually the right choice i think. have fun :)
Johannes Schaub - litb
You make it sound like the answer he "took" is a toy car he's now going to take out for a whirl.. weee!
bobobobo
+161  A: 

static_cast is the first cast you should attempt to use. It does things like implicit conversions between types (such as int to float, or pointer to void*), and it can also call explicit conversion functions (or implicit ones). In many cases, explicitly stating static_cast isn't necessary, but it's important to note that the T(something) syntax is equivalent to (T)something and should be avoided (more on that later). A T(something, something_else) is safe, however, and guaranteed to call the constructor.

static_cast can also cast through inheritance hierarchies. It is unecessary when casting upwards (towards a base class), but when casting downwards it can be used as long as it doesn't cast through virtual inheritance. It does not do checking, however, and it is undefined behavior to static_cast down a hierarchy to a type that isn't actually the type of the object.


const_cast can be used to remove or add const to a variable; no other C++ cast is capable of removing it (not even reinterpret_cast). It is important to note that using it is only undefined if the orginial variable is const; if you use it to take the const of a reference to something that wasn't declared with const, it is safe. This can be useful when overloading member functions based on const, for instance. It can also be used to add const to an object, such as to call a member function overload.

const_cast also works similarly on volatile, though that's less common .


dynamic_cast is almost exclusively used for handling polymorphism. You can cast a pointer or reference to any polymorphic type to any other class type (a polymorphic type has at least one virtual function, declared or inherited). You don't have to use it to cast downwards, you can cast sideways or even up another chain. The dynamic_cast will seek out the desired object and return it if possible. If it can't, it will return NULL in the case of a pointer, or throw std::bad_cast in the case of a reference.

dynamic_cast has some limitations, though. It doesn't work if there are multiple objects of the same type in the inheritance hierarchy (the so-called 'dreaded diamond') and you aren't using virtual inheritance. It also can only go through public inheritance - it will always fail to travel through protected or private inheritance. This is rarely an issue, however, as such forms of inheritance are rare.


reinterpret_cast is the most dangerous cast, and should be used very sparingly. It turns one type directly into another - such as casting the value from one pointer to another, or storing a pointer in an int, or all sorts of other nasty things. Largely, the only guarantee you get with reinterpret_cast is that if you cast the result back to the original type, you will get the same value. Other than that, you're on your own. reinterpret_cast cannot do all sorts of conversions; in fact it is relatively limited. It should almost never be used (even interfacing with C code using void* can be done with static_cast).


C casts are casts using (type)object or type(object). 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

It can therefore be used as a replacement for other casts in some instances, but can be extremely dangerous because of the ability to devolve into a reinterpret_cast, and the latter should be preferred when explicit casting is needed, unless you are sure static_cast will succeed or reinterpret_cast will fail. Even then, consider the longer, more explicit option.

C-style casts also ignore access control when performing a static_cast, which means that they have the ability to perform an operation that no other cast can. This is mostly a kludge, though, and in my mind is just another reason to avoid C-style casts.

I hope this helps!

coppro
I hope others up-vote this answer - it's the only one that actually describes static_cast in enough detail, specifically the limitations on casting within an inheritance hierarchy.
Daniel Earwicker
nice answer mate
Johannes Schaub - litb
Agreed with Earwicker, and +1 from here
jalf
Can you clean up the const_cast section? It is worded confusingly. The last sentence is repeated. Any cast can add const, only const_cast can remove it. The middle section should read more like: "It is undefined behavior to modify a variable defined as const, only possible through use of const_cast"
Greg Rogers
I would recommend as first option dynamic_cast<> which, of course only works as described above. Whenever you can do dynamic_cast<> it will check that the type is really what you believe.
David Rodríguez - dribeas
dynamic_cast is only for polymorphic types. you only need to use it when you're casting to a derived class. static_cast is certainly the first option unless you specifically need dynamic_cast's functinoality. It's not some miraculous silver-bullet "type-checking cast" in general.
jalf
Nicely done... coppro +1
Gishu
One remark about `reinterpret_cast`. Casting back to original type will yield the same value only if intermediate type has enough capacity.
Tadeusz Kopec
nice answer! though too many \`\` 's make it hard to read.
Lazer
+1  A: 

References:

Mr.Ree
+1  A: 

This is not an exact duplicate of this question, but some of the answers there may be of use.

Graeme Perrow
Some good information there. Thank you for the link
e.James