Casting is when one variable is changed from one type to another, e.g. a floating point number to a integer value (3.5 to 3), or a cast of a class to another class.
There is the standard ways of casting a variable from one type to another.
Code:
int value = (int)3.5;
This is the C way of doing things, and since there are things like classes then you want to make sure that the casting is done correctly, or you are told otherwise.
There are 4 different types of casting- static_cast
- dynamic_cast
- const_cast
- reinterpret_cast
I shall do each one in turn, so lets start with
Static_cast
Static casting is for casting between related types, int->float, int*->void* etc.
The basic syntax for a static_cast is
Code:
returnvariable = static_cast<return type>(casting value)
and a example would be
Code:
float fl =3.5;
int intFL = static_cast<int>(fl);
// C similar code would be
int intFL = (int)fl;
this would returned value would be 3, because there is no such thing as 0.5 in integer values.
dynamic_cast
Dynamic casting is when you move from one class type to another that has polymorphic internals. When I say polymorphic, I basically mean that the there is a method that is a virtual method.
For example if you had a class like this
Code:
class baseClass
{
protected :
int x;
public :
baseClass() { x = 55; };
virtual int returnX() { cout << "Base class" << endl; return x;}
void setX(int newXValue) { x = newXValue;}
};
With a base class as
Code:
class subBaseClass : public baseClass
{
public :
subBaseClass() : baseClass() {};
int returnX() { cout << "Subclass" << endl; return x;}
};
The sub class overrides the base class returnX() function.
So if you want to dynamically convert from one class to another you can, the good thing about dynamic casting is that it so some checks to make sure that things can "fit" as such and you can check against the returned value if the casting was done (check against 0 / NULL)
To cast between the two classes you can do something like this
Code:
subBaseClass *sub = new subBaseClass();
baseClass *base = dynamic_cast<baseClass*>(sub);
This would convert the subBaseClass (sub) into a equivalent baseClass (base) type, but still holding onto any values that are within the subBaseClass for example.
Code:
class subBaseClass : public baseClass
{
private :
int y;
public :
subBaseClass() : baseClass() {};
int returnX() { cout << "Subclass" << endl; return x;}
void setY(int v) { y = v;}
int returnY() { return y; }
};
the setY and returnY and the value of y would still be "saved" in the dynamic_cast'ing of that variable into a "lesser" class, but if you cast'd back to a subBaseClass then you will have back the values of "y" in this case, because it does not effect the memory of the variable only allows for baseClass functions to act on that variable, this is good and also a reason would be if you had a function that did take in a class (baseClass in this example) as a parameter and then did some "work" on it and then returned back the class (baseClass), so you could still use this function if you casted back to a baseClass and once returned from the function you can then convert back to the sub class (subBaseClass).
const_cast
Constant casting is basically taking the const (constant) restriction from a variable. If you have a constant value of pi, which makes sense.
Code:
const float pi = 3.14;
But would like to have another value of pi ?? like to 3 decimal places you cannot do
because it is a constant value, but you could take that value and add the extra bit to it
Code:
float newpi = const_cast<float>(pi);
newpi+= 0.002;
reinterpret_cast
The reinterpret casting is abit less type checking safe, compared to the dynamic_cast above, it only checks to see if the casting value can fit into the returning type bit patterns, so that you can convert from different variables but you are never sure if it will work or not and there is no real type checking either. Probably best to use a reinterpret_cast as a last resort really.
A good example is to convert a variable to a void pointer which can then be passed to a function, where the function could try and convert that void pointer to different classes and do some "work" on them. But a smaller example is to convert from a int pointer to a void pointer and then back again.
Code:
#include <iostream>
int main()
{
int *aInt = new int(10);
cout << "A value = " << *aInt << endl;
void *bVoid = reinterpret_cast<void*>(aInt);
int *aBack = reinterpret_cast<int*>(bVoid);
cout << "COME BACK TO ME !! A value again = " << *aBack << endl;
}
This will work fine, because we are just converting from a int to a void back to a int again, if we tried to convert to a float, there is no type checking so it for example
Code:
int *aInt = new int(10);
cout << "A value = " << *aInt << endl;
void *bVoid = reinterpret_cast<void*>(aInt);
int *aBack = reinterpret_cast<int*>(bVoid);
float *aFloat = reinterpret_cast<float*>(bVoid);
cout << "float : "<< *aFloat << endl;
would work, but the aFloat would equal a weird number.
I do really like to have any feedback regarding any tutorial, just reply or PM me.. glad to help, better to share knowledge.
Bookmarks
Algorithms and Data Structures
Java tutorials
Algorithms Forum