Thursday, January 20, 2011

Understanding C++ Type Casting

C++ has 4 different types of casting.
1. const_cast
This cast can used to cast away the the constant.
2. static_cast
This cast can be used to add constant, perform implicit conversion, and to convert from base-class to derived-class.
3. dynamic_cast
This cast can used to convert from derived-class to base-class.
4. reinterpret_cast
This cast can be used to perform conversion from one pointer to another unrelated pointer. This cast is normally used for low-level stuff and not portable.

Person.h
#ifndef PERSON_H_
#define PERSON_H_

#include <string>
using namespace std;

class Person
{
public:
    Person(string name);
    void sayHello() const;
    virtual ~Person();
protected:
    string name;
};

#endif /* PERSON_H_ */

Person.cpp
#include <iostream>
#include "Person.h"
using namespace std;

Person::Person(string name) : name(name)
{
    cout << "Person constructor is being called" << endl;
}

Person::~Person()
{
    cout << "Person destructor is being called" << endl;
}

void Person::sayHello() const
{
    cout << "Hello, " << this->name << endl;
}

Employee.h
#ifndef EMPLOYEE_H_
#define EMPLOYEE_H_

#include "Person.h"

class Employee : public Person
{
public:
    Employee(string name);
    void doWhatever() const;
    virtual ~Employee();
};

#endif /* EMPLOYEE_H_ */

Employee.cpp
#include <iostream>
#include "Employee.h"
using namespace std;

Employee::Employee(string name) : Person(name)
{
    cout << "Employee constructor is being called" << endl;
}

Employee::~Employee()
{
    cout << "Employee destructor is being called" << endl;
}

void Employee::doWhatever() const
{
    cout << "Whatever!" << endl;
}

Main.cpp
#include <iostream>
#include "Person.h"
#include "Employee.h"
using namespace std;

void testReinterpretCast()
{
    cout << "=== Testing reinterpret_cast ===" << endl;
    char* str = "Hello";
    int i = reinterpret_cast<int>(str);
    cout << i << endl; // will print garbage
    str = reinterpret_cast<char*>(i);
    cout << str << endl; // get the value back

    cout << endl;
}


void testDynamicCast()
{
    cout << "=== Testing dynamic_cast ===" << endl;

    // derived-class to base-class
    Employee* e = new Employee("Employee");
    Person* p = dynamic_cast<Person*>(e);
    p->sayHello();
    delete e;

    cout << endl;
}

void testStaticCast()
{
    cout << "=== Testing static_cast ===" << endl;

    // force implicit conversion
    double d = 10.20;
    int i = static_cast<int>(d);
    cout << i << endl;
    // add constant
    const int ci = static_cast<const int>(i);
    cout << ci << endl;

    Person* p = new Person("Person");
    p->sayHello();
    delete p;

    cout << endl;

    // base-class to derived-class
    Person* e = new Employee("Employee");
    e->sayHello();
    Employee* e1 = static_cast<Employee*>(e);
    e1->doWhatever();
    delete e;

    cout << endl;
}

void testConstCast()
{
    cout << "=== Testing const_cast ===" << endl;
    // remove the constant
    const char* cstr = "Hello";
    // char* str = cstr; // Won't compile!
    char* str = const_cast<char*>(cstr);
    cout << str << endl;

    cout << endl;
}

int main()
{
    testStaticCast();
    testConstCast();
    testDynamicCast();
    testReinterpretCast();

    return 0;
}

And this is the output.
=== Testing static_cast ===
10
10
Person constructor is being called
Hello, Person
Person destructor is being called

Person constructor is being called
Employee constructor is being called
Hello, Employee
Whatever!
Employee destructor is being called
Person destructor is being called

=== Testing const_cast ===
Hello

=== Testing dynamic_cast ===
Person constructor is being called
Employee constructor is being called
Hello, Employee
Employee destructor is being called
Person destructor is being called

=== Testing reinterpret_cast ===
4210901
Hello

No comments:

Post a Comment