Cast Operations in C/C++

Lately, i have been looking at my old c/c++ codes. Suddenly i realised that it is quite diffucult to read the code where i have casted different data types to each other by using old style C casting. (Type) Another Type. I Even sometimes cast an integer to an integer pointer. But it is quite hard to read what i am casting into what. So i had a research whether there is something new to casting. And it turns out there was.

Today i am gonna tell you about 4 different casting styles:
1) static_cast
2) const_cast
3) dynamic_cast
4) reinterpret_cast

dynamic_cast (expression)
reinterpret_cast (expression)
static_cast (expression)
const_cast (expression)

    STATIC CAST:

static_cast is the most useful cast. It can be used to perform any implicit cast. When an implicit conversion loses some information, some compilers will produce warnings, and static_cast will eliminate these warnings. Making implicit conversion through static_cast is also useful to resolve ambiguity or to clarify the conversion presence. It also can be used to call an unary constructor, declared as explicit. It also can be used to cast up and down a class hierarchy, like dynamic_cast, except that no runtime checking is performed.

Here is an example:
casting an int to a double for the purpose of avoiding truncation due to integer division:

double result = static_cast(4)/5;

BULLET POINTS ABOUT STATIC CAST:

* Static casts are only available in C++.
* Static casts can be used to convert one type into another, but should not be used for to cast away const-ness or to cast between non-pointer and pointer types.

    CONST CAST:

const_cast is used to apply or remove const or volatile qualifier from a variable.


Here is an example:
casts a const pointer to a non-const pointer to pass into a function:

void func(char *);

const char *x = "abcd";
func(const_cast(x));

BULLET POINTS ABOUT CONST CAST:
*Const casts are only available in C++.
*Const casts are used to strip the const-ness or volatile-ness from a variable.

    DYNAMIC CAST:

dynamic_cast is used on polymorphic pointers or references to move up or down a class hierarchy. Note that dynamic_cast performs runtime-checks: if the object’s type is not the one expected, it will return NULL during a pointer-cast and throw a std::bad_cast exception during a reference-cast.

Here is an example:
class CBase { };
class CDerived: public CBase { };

CBase b; CBase* pb;
CDerived d; CDerived* pd;

pb = dynamic_cast(&d); // ok: derived-to-base
pd = dynamic_cast(&b); // wrong: base-to-derived

The second conversion in this piece of code would produce a compilation error since base-to-derived conversions are not allowed with dynamic_cast unless the base class is polymorphic.

Compatibility note: dynamic_cast requires the Run-Time Type Information (RTTI) to keep track of dynamic types. Some compilers support this feature as an option which is disabled by default. This must be enabled for runtime type checking using dynamic_cast to work properly.

    REINTERPRET CAST:

reinterpret_cast converts any pointer type to any other pointer type, even of unrelated classes. The operation result is a simple binary copy of the value from one pointer to the other. All pointer conversions are allowed: neither the content pointed nor the pointer type itself is checked.

It can also cast pointers to or from integer types. The format in which this integer value represents a pointer is platform-specific. The only guarantee is that a pointer cast to an integer type large enough to fully contain it, is granted to be able to be cast back to a valid pointer.

The conversions that can be performed by reinterpret_cast but not by static_cast have no specific uses in C++ are low-level operations, whose interpretation results in code which is generally system-specific, and thus non-portable. For example:

class A {};
class B {};
A * a = new A;
B * b = reinterpret_cast(a);

This is valid C++ code, although it does not make much sense, since now we have a pointer that points to an object of an incompatible class, and thus dereferencing it is unsafe.

One Last Thing as An Type Identifier :

typeid (expression)

This operator returns a reference to a constant object of type type_info that is defined in the standard header file . This returned value can be compared with another one using operators == and != or can serve to obtain a null-terminated character sequence representing the data type or class name by using its name() member.

// typeid
#include
#include
using namespace std;

int main () {
int * a,b;
a=0; b=0;
if (typeid(a) != typeid(b))
{
cout << "a and b are of different types:\n";
cout << "a is: " << typeid(a).name() << '\n';
cout << "b is: " << typeid(b).name() << '\n';
}
return 0;
}

RESULT:


a and b are of different types:
a is: int *
b is: int

When typeid is applied to classes typeid uses the RTTI to keep track of the type of dynamic objects. When typeid is applied to an expression whose type is a polymorphic class, the result is the type of the most derived complete object:

// typeid, polymorphic class
#include
#include
#include
using namespace std;

class CBase { virtual void f(){} };
class CDerived : public CBase {};

int main () {
try {
CBase* a = new CBase;
CBase* b = new CDerived;
cout << "a is: " << typeid(a).name() << '\n';
cout << "b is: " << typeid(b).name() << '\n';
cout << "*a is: " << typeid(*a).name() << '\n';
cout << "*b is: " << typeid(*b).name() << '\n';
} catch (exception& e) { cout << "Exception: " << e.what() << endl; }
return 0;
}

Result:

a is: class CBase *
b is: class CBase *
*a is: class CBase
*b is: class CDerived

Notice how the type that typeid considers for pointers is the pointer type itself (both a and b are of type class CBase *). However, when typeid is applied to objects (like *a and *b) typeid yields their dynamic type (i.e. the type of their most derived complete object).

If the type typeid evaluates is a pointer preceded by the dereference operator (*), and this pointer has a null value, typeid throws a bad_typeid exception.

Links:
http://www.cplusplus.com/doc/tutorial/typecasting/
http://www.cprogramming.com/reference/typecasting/
http://www.cppreference.com/wiki/keywords/casting_comparison

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s