Typecasting in C++: static, dynamic and others

Share the Article

Typecasting in c++ is of 4 types. This is explained below:

static_cast:

This is first and simple kind of typecasting in c++. This is used to perform all conversions that are well-defined.

Used For Conversions between built-in types: These include “safe” conversions that the compiler would allow you to do without a cast. i.e., cast from smaller built-in type to bigger built-in type, like,

  • int to long
  • float to double

Since, these are well defined cases, In such cases, there are no errors or warnings both with and without static_cast

int ivar; long lvar; lvar = ivar; //This is ok lvar = static_cast<long>(ivar); //This is also ok float fvar; double dvar; dvar = fvar; //This is ok dvar = static_cast<double>(fvar); //This is also ok

This is also used in Less-safe conversions that are nonetheless well defined. This cast may result in loss of data, like, cast from bigger built-in type to smaller built-in type, like,

  • long to int
  • double to float
int ivar; long lvar; ivar = lvar; //This is NOT ok ivar = static_cast<long>(lvar); //This is also ok float fvar; double dvar; fvar = dvar; //This is NOT ok fvar = static_cast<double>(dvar); //This is also ok

The compiler generate warnings when such conversions are used without static_cast.

warning when static_cast not used

Used For Conversion between any pointer to void* pointer & vice versa

The first conversion type includes, safe-conversion from any pointer to void* type and second is less safe reverse conversion.

int *ivar; void *vvar; vvar = ivar; //This is ok vvar = static_cast<void*>(ivar) //This is also ok ivar = vvar; //This is NOT ok ivar = static_cast<int*>(vvar); //This is ok

Used For Conversion during Upcasting & Downcasting in inheritance: Cast from Derived class pointer to Base class pointer when no virtual functions are present (Upcasting). This is safe operation.

Base *bptr = new Base(); Derived *dptr = new Derived(); bptr = dptr; //This is ok bptr = static_cast<Base*>(dptr); //This is also ok

Also Downcasting, which is less safe, cast from Base class pointer to derived class pointer

#include <iostream> //main header using namespace std; //for namespace class MFBase { public: virtual ~MFBase() {} }; class MFDerived : public MFBase { public: virtual ~MFDerived() {} }; int main() //main function { MFBase *bptr = new MFBase(); MFDerived *dptr = new MFDerived(); dptr = bptr; //This is NOT ok dptr = static_cast<MFDerived*>(bptr) //This is ok return 0; }

Without static_cast, the compiler may generate errors in down-cast.

downcasting warning due to use of dynamic_cast

const_cast

The programs uses this cast to convert from a const type to a non-const type or from a volatile to a non-volatile type

If the expression includes any other conversion then they must be done using a separate cast. Otherwise, the compilation of the code shall produce an error.

Example,

Without const_cast, error generated:

const int civar = 8; int *ivar = &civar; //This is NOT ok
error due to non-usage of const_cast with const

const_cast will remove the warning

int *ivar = const_cast<int*>(&civar);

Similary, const_cast will cast a type from volatile to non-volatile

volatile int vi = 8; int *i = &vi; //This is NOT ok
error due to non-usage of const_cast with volatile

Following is also example of NOT ok

volatile int *vi; const int *ci = vi;
compiler error when const_cast is not used

With const cast, there will be no error/warning in such conversions

const int *civar = const_cast<const int*>(vivar);

dynamic_cast

This is a special cast and programs use this cast for type-safe downcasting. When dynamic_cast try to cast down to a particular type, the return value will be a pointer to the desired type only.

If dynamic_cast cannot downcast an object to desired type then it returns NULL value.

The dynamic_cast is dependent on polymorphic hierarchy – one with virtual functions. This is because dynamic_cast uses information stored in the VTABLE for determining the actual type at runtime.

#include <iostream> //main header using namespace std;//for namespace class MFBase { public: virtual ~MFBase(){} }; class MFDerived : public MFBase { }; int main() //main function { MFBase *b1 = new MFBase; MFDerived *d1 = dynamic_cast<MFDerived*>(b1); //Invalid cout << d1 << endl; MFBase *b2 = new MFDerived; MFDerived *d2 = dynamic_cast<MFDerived*>(b2); // Valid cout << d2 << endl; return 0; }

The output of dynamic_cast is:

0 0x2603c40

The dynamic_cast will work only if the class uses virtual functions. Otherwise, if there are no virtual function, the compiler will generate error:

dynamic_cast leads to error when used in non-polymorphic classes

reinterpret_cast

This is the least safe cast compared to other casts. This cast converts any type to completely different type. The reinterpret_cast assumes that an object is just a bit pattern. This cast converts by treating the bit pattern to an entirely different type of object. This method is similar to C-style casts. This is a low-level cast.

This cast can potentially produce bugs therefore, users should use this very carefully.

#include <iostream> //main header using namespace std;//for namespace class MFBase { int yvar; public: ~MFBase(){} }; class MFDerived : public MFBase { int xvar; }; int main() { MFBase *bvar1 = new MFDerived; int *ivar = reinterpret_cast<int*>(bvar1); cout << ivar << endl; MFBase *bvar2 = reinterpret_cast<MFBase*>(ivar); cout << bvar2 << endl; return 0; }

The output is:

0xb2cc20 0xb2cc20

Main Funda: Proper typecasting in c++ code is very important in C++ program and C-style casts should never be used

Related topics:

 What are the drawbacks of using enum ?
Which member functions are generated by compiler in class?
How to stop compiler from generating special member functions?
Compiler Generated Destructor is always non-virtual
How to make a class object un-copyable?
Why virtual functions should not be called in constructor & destructor ?
Explaining C++ casts
How pointer to class members are different ?
How std::forward( ) works?
What is reference collapsing?
How std::move() function works?
How delete keyword can be used to filter polymorphism
Rule of Three

Share the Article

Leave a Reply

Your email address will not be published. Required fields are marked *