R@M3$H.NBlog

Casting in C++

18 April, 2013 - 3 min read

static_cast

static_cast is used for cases where you basically want to reverse an implicit conversion, with a few restrictions and additions. static_cast performs no runtime checks. This should be used if you know that you refer to an object of a specific type, and thus a check would be unnecessary. Example:

void func(void *data) {
  // conversion from MyClass* -> void* is implicit
  MyClass *c = static_cast<MyClass*>(data);
  ...
}

int main() {
  MyClass c;
  start_thread(&func, &c)  // func(&c) will be called
      .join();
}

In this example, you know that you passed a MyClass object, and thus there is no need for a runtime check to ensure this.

dynamic_cast

dynamic_cast is used for cases where you don't know what the dynamic type of the object is. You cannot use dynamic_cast if you downcast and the argument type is not polymorphic. An example

if(JumpStm *j = dynamic_cast<JumpStm*>(&stm)) {
  ...
} else if(ExprStm *e = dynamic_cast<ExprStm*>(&stm)) { 
  ...
}

dynamic_cast returns a null pointer if the object referred to doesn't contain the type casted to as a base class (when you cast to a reference, a bad_cast exception is thrown in that case).

The following code is not valid, because Base is not polymorphic (doesn't contain a virtual function):

struct Base { };
struct Derived : Base { };
int main() { 
  Derived d; Base *b = &d;
  dynamic_cast<Derived*>(b); // invalid
}

An "up-cast" is always valid with both static_cast and dynamic_cast, and also without any cast, as an "up-cast" is an implicit conversion.

Regular Cast

These casts are also called c-style cast. A c-style cast is basically identical to trying out a range of sequences of C++ casts, and taking the first c++ cast that works, without ever consideringdynamic_cast. Needless to say that this is much more powerful as it combines all of const_cast,static_cast and reinterpret_cast, but it's also unsafe because it does not usedynamic_cast.

In addition, C-style casts not only allow you to do this, but also allow you to safely cast to a private base-class, while the "equivalent" static_cast sequence would give you a compile time error for that.

Some people prefer c-style casts because of their brevity. I use them for numeric casts only, and use the appropriate C++ casts when user defined types are involved, as they provide stricter checking.

 

const_cast conversion adds or removes const
static_cast conversion performs basic conversions
dynamic_cast conversion performs checked polymorphic conversions
reinterpret_cast conversion performs general low-level conversions
standard conversions implicit conversions from one type to another

 

END