home > resources > c++ coding standard > online version

Prefer C++ Casts

The traditional way of casting in C is still possible in C++, but alternative options are available which provide much better diagnoses of usage errors and are much easier to indentify and maintain.

These new casts are :

const_cast<T>(e)

Casts away the const-ness of objects, variables or pointers. It gives an error when the types differ more than in const and volatile modifiers.

Don't use this to cast away const-ness of objects that were originally defined as being const and on which non-const operations are being executed. Doing this, results in undefined behaviour.

You typically use this when you need to access an api that incorrectly defines a function signature. When you are 100% sure that the function you want to call doesn't perform non-const operations on the argument, you can safely cast away the const-ness of the argument that was initially defined as being const.

Example 5-2. const_cast Example

int countChars(char *pString, char character);
  
const char *p_somestring = "Let's make things better";
int result = countChars(const_cast<char*>(p_somestring), 'e');

dynamic_cast<T>(e)

Makes it possible to safely downcast pointers and references to base classes. It thus returns the appropriate sub-object in the hierarchy chain. It returns 0 if this cast wasn't possible on pointers and throws the bad_cast exception if the cast wasn't possible on references. This effectively says "convert this Object into a Penguin or give me 0 if its not an Penguin,". This provides dynamic typing, you don't know what will happen until run-time.

Example 5-3. dynamic_cast Example

class B { /* at least one virtual function */ };
class D : public B { /* ... */ };
        
B* p_b1 = new B;
B* p_b2 = new D;
        
                          D* p_d1 = dynamic_cast<D*>(p_b1);       /* will be 0 */
                          D* p_d2 = dynamic_cast<D*>(p_b2);       /* will be an object of type D* */

reinterpret_cast<T>(e)

This type of casts treats pointers and references as incomplete types. Using the reinterprete_cast yields values that are typically not guaranteed to be usable without casting back to their orginal types. It's difficult to say more about this kind of casts since their applicability is very implementation dependent.

Example 5-4. reinterpret_cast Example

void someFunction(char *p_string) { *p_string = 'x'; }
typedef void (*FPType)(const char*);
FPType p_functionpointer = reinterpret_cast<FPType>(&someFunction);
/* calling someFunction through p_functionpointer is not guaranteed to work */

static_cast<T>(e)

This is very similar to the old C-style casts. Only use it when none of the above seem to fit the bill. It will only succeed if there's an implicit conversion possible either from T to the type of e, or from the type of e to T.

Example 5-5. static_cast Example

Fraction fraction(1,2);
double d = static_cast<double>(fraction);