C++ – Type Casting

Typecasting in C++ allows us to perform conversion between types.

C-Style Cast
This was carried forward from C- language. Compiler does not perform type checking and hence this type of cast can result in run time errors/ undefined behavior. Therefore It is best to avoid them in the program. For example,  consider the following.

Example 1

#include <iostream>
#include <string>
using namespace std;
struct A{
int first;
int second;
A(int first, int second):first(first), second(second){}
};
struct B{
string third;
string fourth;
};
int main() {
A* a = new A(1,2);
B* b = (B*)a;
cout<<b->third; //Run-time error
return 0;
}
view raw C-Style Cast hosted with ❤ by GitHub

Example 2

#include <iostream>
using namespace std;
int main(){
char a = 'c';
int *b = (int*)&a;
cout<<*b; //Undefined behavior because integer pointer tries to access 4 bytes of memory although only 1 byte belongs to it.
return 0;
}
view raw C-Style Cast2 hosted with ❤ by GitHub

C++ introduced four new casting operators – static_cast, dynamic_cast, const_cast and reinterpret_cast.

static_cast
static_cast addresses many of the pitfalls associated with the C-style cast. It performs thorough type checking at compile time and throws an error when there is a type mismatch. The earlier examples can therefore be changed to the following. Both the programs will throw compile time errors.

Example 1

#include <iostream>
#include <string>
using namespace std;
struct A{
int first;
int second;
A(int first, int second):first(first), second(second){}
};
struct B{
string third;
string fourth;
};
int main() {
A* a = new A(1,2);
B* b = static_cast<B*>(a); //Compiler Error
cout<<b->third;
return 0;
}
view raw static_cast hosted with ❤ by GitHub

Example 2

#include <iostream>
using namespace std;
int main(){
char a = 'c';
int *b = static_cast<int*>(&a); //Compiler Error
cout<<*b;
return 0;
}
view raw static_cast2 hosted with ❤ by GitHub

static_cast does not work well with inheritance. When we have a pointer to a base class that may or may not be pointing to an object of its derived class and we try to explicitly convert this pointer to a pointer of the derived class, static_cast will happily do the conversion for us. This is not desirable as the base class pointer may as well be pointing to an object of the base class.

#include <iostream>
using namespace std;
class Base_Class {
public:
virtual void func() {}
};
class Derived_Class :public Base_Class {
public:
void func() {}
};
int main() {
Base_Class * a = new Base_Class();
Derived_Class *b = static_cast<Derived_Class*>(a);
if (!b) cout << "b is nullptr";
else cout << "b is not nullptr";
cin.get();
}
view raw static_cast3 hosted with ❤ by GitHub

Output:

b is not nullptr

dynamic_cast
dynamic_cast addresses the pitfalls associated with compile time type checking. It performs type checking during run-time and is able to catch the above incorrect type conversion. dynamic_cast returns a null pointer when the cast performed is illegal.

#include <iostream>
using namespace std;
class Base_Class {
public:
virtual void func() {}
};
class Derived_Class :public Base_Class {
public:
void func() {}
};
int main() {
Base_Class * a = new Base_Class();
Derived_Class *b = dynamic_cast<Derived_Class*>(a);
if (!b) cout << "b is nullptr";
else cout << "b is not nullptr";
cin.get();
}
view raw Dynamic_cast hosted with ❤ by GitHub

Output:

b is nullptr

There are two other casting operators in C++: const_cast and reinterpret_cast. const_cast allows us to remove the ‘const’ and ‘volatile’ properties of types. It works with pointers and references.

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s