Wednesday, June 5, 2013

Why bother to use 4 types of casting in C++?

Why bother to use 4 types of casting in C++?

Even in The Language C++ programming 3ed does not organize these 4 types casting together.
I am trying to figure out why C++ bothers to use these 4 types of casting. Why 4 types are complete?

By exploring why there are 4 types of casting, then we may know when we can use which one.

The first step I have done is to Google like "why C++ introduce 4 types of casting"?
I could not find a complete answer, most of the tutorials or articles just drop a few lines, then directly jump to teach you how to use these 4 types of casting.

The answer
"The ailments of C-style cast have been known for years. C++ offers a superior alternative in the form of new cast operators. They document the programmer's intent more clearly while preserving the compiler's ability to catch potential bugs like the ones shown above. C++ has four new cast operators" [5] http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=134

Using the new style casts clarifies the programmer’s intent to the compiler and enables the
compiler to catch casting errors.[1]


I don't feel above answer is persuasive, until I read below references. 
==================================================================

Most helpful tutorial of this topic is: 
[1]Appendix I: C++ Casts and Run-Time Type Identification(In the book: starting out with c++ early objects)
It gives me almost complete answer.


These 2 gives an idea is that  A c-style cast can cover all 3 cast operators(const_cast, static_cast, reinterpret_cast), and dynamic_cast gives new function which C-style dose not give.(Probably this idea originally comes from somewhere, but below 2 links did not mention)

[2]http://stackoverflow.com/questions/28002/regular-cast-vs-static-cast-vs-dynamic-cast
[3]http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=134

This one you can verify you thought, when you think you have solid idea of C++ casting:
[4]http://www.cplusplus.com/doc/tutorial/typecasting/

Definition of complete object refers to: http://msdn.microsoft.com/en-us/library/x9wzb5es(v=vs.80).aspx

I just search in the google, there must be some other resources where we can get a complete answer, otherwise in the reference I mentioned above, the authors couldn't present their illustration.

========================================================================
Then I got my summary. I think it can help you also.
Please read all the reference above, or I don't think you can understand my summary. It may takes a few hours, but totally worth to do.

(c-style, dynamic_cast) = ( [const_cast, static_cast, reinterpret_cast],  dynamic_cast)

1. static_cast and reinterpret_cast are distinguished by if there are information at compile time.
    Say class Child derived from class Father, object child can static_cast to object father, vice versa. That's because when we define class Child, we give some information. And in char, long, float ..., the compiler know the information how to cast, so they can apply static_cast to each other.
    But if class Mother and Class Father do not have any relationship of inheritance, then reinterpret_cast is your only choice. This may help if Mother and Father have some similar data arrangement in the class definition, otherwise I don't any sense. This is quite a low level manipulation. When we use it, we must have a bad design.

2. const_cast is only used to cast const variable to non-const. quite simple and not related to other cast operators

3. dynamic_cast is relative to static_cast, they are a pair of Yin-Yang.
static_cast is used to check error at compile time, but dynamic check error at run-time.

With these 3 points and the formula, it's easy to decide when to use a certain cast operator.

========================================================================

There are some other differences between static_cast/dynamic_cast. (don't read this if you fell it's mouthful)

    You can static_cast base object to derived object, or vice versa, but you will see run-time error(eg. use a base pointer to call a member function only defined in derived class ).
    You only can dynamic_cast derived object to base object, unless base class is polymorphic.

    When base class is polymorphic, dynamic_cast<CDerived*>(pbb) will be 0, if pbb not actually point to CDerived object. That is why we use dynamic_cast. With the 0 being returned, we can know if the object derived from the class <CDerived*>. Why is that helpfull and for details, check the reference[1][4].




No comments:

Post a Comment