To convert an expression of a given type into another is known as type-casting. There are basically two types of type conversion:
- Implicit Type Conversion
- Explicit Type Conversion
Casting operators comes under Explicit type conversion, in order to control the types of conversion between C++ classes and we have four type of casting operators namely:
- Static_cast<new type> (expression)
- Dynamic_cast<new type> (expression)
- const_cast<new type> (expression)
- reinterpret_cast<new type> (expression)
Static Cast
This perform conversion between related classes, not only from derived to base class but also from base to derived class. The conversion ensures that the classes are related if successful conversion is done. There is no safety check to make sure that the object being converted is complete full object of the destination type. This is also called compile time cast since there are no action performed during run-time as in case of dynamic_cast.
#include <iostream>
using namespace std;
class TsBase {};
class TsDerived: public TsBase {};
class TsAlien {};
int main() {
TsBase *bptr1 = new TsBase;
// valid conversion from base to derived related classes
TsDerived *dptr1 = static_cast<TsDerived*>(bptr1);
TsDerived *dptr2 = new TsDerived;
// valid conversion from derived to base related classes
TsBase *bptr2 = static_cast<TsBase*>(dptr2);
// Invalid conversion from base to unrelated class
TsAlien *aptr = static_cast<TsAlien>(*bptr1);
return 0;
}
Dynamic Cast
This performs a runtime cast that verifies that the valid complete object of the destination type is converted else it evaluates to null. So basically dynamic cast operator comes at a cost during runtime to validate type and completeness of requested class.
Base class to derived class conversion are not allowed with dynamic_cast, it will give you compilation error, unless the base class is polymorphic. In such case it performs type checking during runtime to ensure that the conversion yield valid complete object.
#include <iostream>
using namespace std;
class TsBase { virtual void dummy() {} };
class TsDerived : public TsBase {};
int main() {
TsBase *bptrb = new TsBase;
TsBase *bptrd = new TsDerived;
TsDerived *dptr;
dptr = dynamic_cast<TsDerived>(bptrd); // valid complete conversion
if (dptr == NULL) { cout<<"This statement is never reached"<<endl; }
dptr = dynamic_cast<TsDerived>(bptrb); // Invalid conversion downcasting
if (dptr == NULL) { cout<<"This is invalid incomplete conversion"<<endl;
return 0;
}
Const Cast
This type of conversion manipulates the constness of an object, either to be set or removed.
#include <iostream>
using namespace std;
void display (char *cptr) {
cout<<"Title: "<< cptr <<endl;
}
int main() {
const char *ccptr = "Techstroke is awesome";
display(const_cast<char*>(ccptr));
return 0;
}
Reinterpret Cast
As the name suggest this type of conversion reinterprets the type of object being converted. This can convert any pointer to any other pointer type, even of unrelated classes. It can also convert pointers to or from integer types. The format in which this integer value represents a pointer is platform-specific, and thus non-portable.
#include <iostream>
using namespace std;
class TsA {};
class TsB {};
int main() {
TsA *aptr = new TsA;
TsB *bptr = reinterpret_cast<TsB*>(aptr); // no safety check, valid c++ code
return 0;
}