TITLE: new casting in plain english (Newsgroups: comp.std.c++, 26 Feb 97) BOTTING: dick@silicon.csci.csusb.edu (Dr. Richard Botting) >I'm feeling like I'm lost in twisty maze of little passages >that all look alike.... Or was it a maze of little twisty passages >that all look alike? > >In the December Draft/HTML Version I find: ... > >I could do with a simple briefing describing the differences between > a cast > a constant cast > a static cast > a dynamic cast > a reinterpret cast CLAMAGE: Stephen.Clamage@Eng.Sun.COM (Steve Clamage) I deleted the quotes from the draft, which were the introductory paragraph describing each kind of cast. The introductory paragraphs are (intentionally) nearly identical. The remainder of each section describes its cast in detail. The draft standard uses 7 pages to describe all the casts. I don't think a complete explanation could be much smaller, so I'll use the pedagogical device of oversimplification to keep things down to the size of a netnews article. First I'll provide a brief rationale for introducing the four new casts. The old-style cast could be used for several different purposes. In particular, it was commonly used for - changing constness: (char*)ptr_to_const_char - converting a value to a value of a different type: (int)floating_value - navigating a hierarchy: (derived*)ptr_to_base - type "punning": (int*)ptr_to_void (Type punning generally means treating an object, particularly a pointer, as an object of a different type.) When the notations (T)e and T(e) are both allowed, they are exactly equivalent. Sometimes only one of the notations is allowed. When you see a cast expression like "(T)(expr)" it is often hard to tell why the cast is there. Also, it is often hard to tell whether the cast is likely to be dangerous or nonportable. Finally, there is no way to scan a source file and reliably find every cast, unless you have a "smart editor" that can fully parse C++ source code. C++ introduced four new cast operators to address those problems: Each cast is intended for a particular purpose (although there is some overlap), and each cast uses a new keyword that can be found easily with any text editor. Here is an oversimplified description of each cast. In particular, I'm ignoring references and discussions of lvalue vs rvalue. (Generally speaking, what is true for pointers is true for references. Generally speaking, casting yields an rvalue, except that casting a reference generally yields an lvalue.) static_cast: primarily for value conversion - can perform any conversion which is allowed implicitly - can reverse any implicit conversion except cannot downcast from a virtual base class - cannot remove constness dynamic_cast: primarily for hierarchy navigation - can upcast a ptr_to_derived to any of its unambiguous base classes - can downcast a ptr_to_base (including virtual base classes) to any unambiguous derived class if the class is polymorphic. Indicates failure if the object isn't really the right type. - can cast "sideways" in a hierarchy if the class is polymorphic - cannot remove constness reinterpret_cast: primarily for type punning - can convert pointers to integer types and vice versa - can convert a pointer to an unrelated pointer type - results are implementation-defined and might not work - cannot remove constness const_cast: primarily to remove constness - can change the const and volatile specifiers of a type - cannot otherwise change the type The old-style cast is now defined as a static_cast or reinterpret_cast possibly followed by a const_cast. (The only dynamic_casts that an old-style cast can perform can also be performed by a static_cast. If an old-style cast could be performed by both a static_cast and a reinterpret_cast, the static_cast interpretation is chosen.)