Casts Made Easy!
In C, casting was easy. You could
cast like you called a function:
int i = int('A');
You can also do this in C++. But
the only reason it's there is for backwards compatibility with
C. Casting like this will eventually cause havoc in a large program,
and it also only provides support for primitive types. In C++,
there is a set of 4 ANSI C++ casts: static_cast, reinterpret_cast,
const_cast, and (the much feared) dynamic_cast. Here I will provide
an explanation and example for each cast, to make them easier
to understand and possibly save some programs using C casting
:)
First, the simplest and most common,
static_cast. This cast simply converts from one data type to another.
The syntax is:
static_cast<new_type>(argument);
where new_type is the type
to be converted to, and argument is the data you wish to
convert. Converting my earlier example from C to C++ yields:
int i = static_cast<int>('A');
Note that new_type can
be any data type, primitive or user-defined. argument can
also be a variable:
char letter = 'A';
int i = static_cast<int>(letter);
That's all there really is to
static_cast.
The next type of (and hardest
to spell) cast is reinterpret_cast. Unlike static_cast, reinterpret_cast
doesn't actually change any data, it causes the data to be reinterpreted,
or looked at differently, by the compiler. The most common use
of reinterpret_cast is casting a void* pointer, such as the one
returned from malloc():
int* num = reinterpret_cast<int*>(malloc(100));
But then again, who needs malloc()
when you've got new? reinterpret_cast can be dangerous, however,
like in this example:
int num = 5;
int* pNum = #
double* pDouble = reinterpret_cast<double*>(pNum);
cout << *pDouble << endl;
This outputs integer data as if
it were double (or floating point) data. Nothing but bad things
can result from that! You'll probably get a lot of garbage printed
to the screen.
The moral here? Be careful with
reinterpret_cast!
Next we'll look at const_cast.
const_cast is for adding/removing const from a variable. There
usually isn't a reason to do this, and if there is, it's probably
bad programming. However, every so often there's a situation that
you just can't get around, and have to use const_cast. (sorta
like goto). Here's a simple example:
void Display(int* data)
{
cout << *data << endl;
}
int main()
{
const int num = 5;
Display(const_cast<int*>(&num));
return 0;
}
If you don't use const_cast here,
the compiler will give you an error along the lines of "no
match for function..." because const data can't be passed
into non-const function data. Redundant? Yes. Avoidable? Yes.
Occasionally necessary? Yes.
Finally, it's time to tackle the
one no one else wants to: dynamic_cast. There's a lot of confusion
over what it does, why to use it, when to use it, etc. The formal
(i.e. newbie-scaring) description says that it "is a polymorphic
cast that verifies the runtime type of the object being cast".
Ouch. To make it clearer, consider this example:
class Base
{
public
virtual void DoSomething() {cout << "Base" <<
endl;}
};
class Derived : public Base
{
public:
virtual void DoSomething() {cout << "Derived"
<< endl;}
};
int main()
{
Derived derived;
Base* pBase = &derived;
// the base pointer points to a derived
// object. Legal, but confusing.
Derived* pDerived = dynamic_cast<Derived*>(pBase);
// because pBase is actually a pointer t
// o a Derived at runtime,
the
// cast succeeds and pDerived is assigne
// d the value of pBase
if (pDerived)
pDerived->DoSomething();
else
cout << "Bad cast" << endl;
return 0;
}
In this example, the pointer to
Base was assigned the address of a Derived object. That's legal.
Then, a pointer to a Derived is declared. A check is performed
with dynamic_cast: if, at runtime, the argument (pBase) is of
type new_type (Derived), then dynamic_cast returns a pointer to
Derived with the value pBase. So, pDerived is assigned the value
of a base pointer which without a cast would be impossible.
dynamic_cast returns NULL if the
cast fails, so to prevent a memory leak ALWAYS check if the cast
succeeded with an if...else. Classes used with dynamic_cast must
have at least one virtual function.
Well, that's it. I hope you've
learned something from all of this! Please leave any comments/feedback
that come to mind, everything is appreciated! If you need anything
cleared up, please feel free to email me at kavutitan26@yahoo.com.
Enjoy!
->Andrew-< |