📄 mi2.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" "http://www.w3.org/TR/REC-html40/frameset.dtd">
<HTML LANG="EN">
<HEAD>
<TITLE>More Effective C++ | Item 2: Prefer C++-style casts</TITLE>
<LINK REL=STYLESHEET HREF=../INTRO/ECMEC.CSS>
<SCRIPT LANGUAGE="Javascript" SRC="../JAVA/COOKIE.JS"></SCRIPT>
<SCRIPT LANGUAGE="Javascript">var imagemax = 0; setCurrentMax(0);</SCRIPT>
<SCRIPT LANGUAGE="Javascript" SRC="../JAVA/DINGBATS.JS"></SCRIPT>
<SCRIPT LANGUAGE="Javascript">
var dingbase = "MI2_DIR.HTM";
var dingtext = "MEC++ Item M2, P";
if (self == top) {
top.location.replace(dingbase + this.location.hash);
}
</SCRIPT>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" ONLOAD="setResize()">
<!-- SectionName="M2: Prefer C++-style casts" -->
<A NAME="77216"></A>
<DIV ALIGN="CENTER"><FONT SIZE="-1">Back to <A HREF="./MI1_FR.HTM" TARGET="_top">
Item 1: Distinguish between pointers and references
</A> <BR> Continue to <A HREF="./MI3_FR.HTM" TARGET="_top">Item 3: Never treat arrays polymorphically</A></FONT></DIV>
<A NAME="p9"></A>
<A NAME="p12"></A>
<P><A NAME="dingp1"></A><font ID="mititle">Item 2: Prefer C++-style casts.</font><SCRIPT>create_link(1);</SCRIPT>
</P>
<A NAME="77217"></A>
<A NAME="77218"></A>
<P><A NAME="dingp2"></A>
Consider the lowly cast. Nearly as much a programming pariah as the <CODE>goto</CODE>, it nonetheless endures, because when worse comes to worst and push comes to shove, casts can be necessary. Casts are especially necessary when worse comes to worst and push comes to <NOBR>shove.<SCRIPT>create_link(2);</SCRIPT>
</NOBR></P><A NAME="10133"></A>
<P><A NAME="dingp3"></A>
Still, C-style casts are not all they might be. For one thing, they're rather crude beasts, letting you cast pretty much any type to pretty much any other type. It would be nice to be able to specify more precisely the purpose of each cast. There is a great difference, for example, between a cast that changes a pointer-to-<CODE>const</CODE>-object into a pointer-to-non-<CODE>const</CODE>-object (i.e., a cast that changes only the <CODE>const</CODE>ness of an object) and a cast that changes a pointer-to-base-class-object into a pointer-to-derived-class-object (i.e., a cast that completely changes an object's type). Traditional C-style casts make no such distinctions. (This is hardly a surprise. C-style casts were designed for C, not <NOBR>C++.)<SCRIPT>create_link(3);</SCRIPT>
</NOBR></P><A NAME="10134"></A>
<P><A NAME="dingp4"></A>
A second problem with casts is that they are hard to find. Syntactically, casts consist of little more than a pair of parentheses and an identifier, and parentheses and identifiers are used everywhere in C++. This makes it tough to answer even the most basic cast-related questions, questions like, "Are any casts used in this program?" That's because human readers are likely to overlook casts, and tools like <CODE>grep</CODE> cannot distinguish them from non-cast constructs that are syntactically <NOBR>similar.<SCRIPT>create_link(4);</SCRIPT>
</NOBR></P><A NAME="77185"></A>
<P><A NAME="dingp5"></A>
C++ addresses the shortcomings of C-style casts by introducing four new cast operators, <CODE>static_cast</CODE>, <CODE>const_cast</CODE>, <CODE>dynamic_cast</CODE>, and <CODE>reinterpret_cast</CODE>. For most purposes, all you need to know about these operators is that what you are accustomed to writing like <NOBR>this,<SCRIPT>create_link(5);</SCRIPT>
</NOBR></P><A NAME="77186"></A>
<UL><PRE>(<I>type</I>) <I>expression</I>
</PRE>
</UL><A NAME="77187"></A>
<A NAME="dingp6"></A><P><A NAME="dingp6"></A>you should now generally write like <NOBR>this:<SCRIPT>create_link(6);</SCRIPT>
</NOBR></P>
<A NAME="77188"></A>
<UL><PRE>static_cast<<I>type</I>>(<I>expression</I>)
</PRE>
</UL><A NAME="77189"></A>
<P><A NAME="dingp7"></A>
For example, suppose you'd like to cast an <CODE>int</CODE> to a <CODE>double</CODE> to force an expression involving <CODE>int</CODE>s to yield a floating point value. Using C-style casts, you could do it like <NOBR>this:<SCRIPT>create_link(7);</SCRIPT>
</NOBR></P><A NAME="77190"></A>
<UL><PRE>int firstNumber, secondNumber;
<A NAME="78576"></A>
...
<A NAME="78575"></A>
double result = ((double)firstNumber)/secondNumber;</PRE>
</UL><A NAME="78788"></A>
<P><A NAME="dingp8"></A>
With the new casts, you'd write it this <NOBR>way:<SCRIPT>create_link(8);</SCRIPT>
</NOBR></P>
<A NAME="78789"></A>
<UL><PRE>double result = static_cast<double>(firstNumber)/secondNumber;</PRE>
</UL>
<A NAME="78790"></A><P><A NAME="dingp9"></A>
<A NAME="p13"></A>Now <I>there's</I> a cast that's easy to see, both for humans and for <NOBR>programs.<SCRIPT>create_link(9);</SCRIPT>
</NOBR></P><A NAME="77196"></A>
<P><A NAME="dingp10"></A>
<CODE>static_cast</CODE> has basically the same power and meaning as the general-purpose C-style cast. It also has the same kind of restrictions. For example, you can't cast a <CODE>struct</CODE> into an <CODE>int</CODE> or a <CODE>double</CODE> into a pointer using <CODE>static_cast</CODE> any more than you can with a C-style cast. Furthermore, <CODE>static_cast</CODE> can't remove <CODE>const</CODE>ness from an expression, because another new cast, <CODE>const_cast</CODE>, is designed specifically to do <NOBR>that.<SCRIPT>create_link(10);</SCRIPT>
</NOBR></P><A NAME="81192"></A>
<P><A NAME="dingp11"></A>
The other new C++ casts are used for more restricted purposes. <CODE>const_cast</CODE> is used to cast away the <CODE>const</CODE>ness or <CODE>volatile</CODE>ness of an expression. By using a <CODE>const_cast</CODE>, you emphasize (to both humans and compilers) that the only thing you want to change through the cast is the <CODE>const</CODE>ness or <CODE>volatile</CODE>ness of something. This meaning is enforced by compilers. If you try to employ <CODE>const_cast</CODE> for anything other than modifying the <CODE>const</CODE>ness or <CODE>volatile</CODE>ness of an expression, your cast will be rejected. Here are some <NOBR>examples:<SCRIPT>create_link(11);</SCRIPT>
</NOBR></P><A NAME="78221"></A>
<UL><PRE>class Widget { ... };
class SpecialWidget: public Widget { ... };
</PRE>
</UL><A NAME="78225"></A>
<UL><PRE>void update(SpecialWidget *psw);
</PRE>
</UL><A NAME="78295"></A>
<UL><PRE>SpecialWidget sw; // sw is a non-const object,
const SpecialWidget& csw = sw; // but csw is a reference to
// it as a const object
<A NAME="78296"></A>
update(&csw); // error! can't pass a const
// SpecialWidget* to a function
// taking a SpecialWidget*
<A NAME="78297"></A>
update(const_cast<SpecialWidget*>(&csw));
// fine, the constness of &csw is
// explicitly cast away (and
// csw — and sw — may now be
// changed inside update)
<A NAME="78312"></A>
update((SpecialWidget*)&csw);
// same as above, but using a
// harder-to-recognize C-style cast
<A NAME="78313"></A>
Widget *pw = new SpecialWidget;
<A NAME="78320"></A>
update(pw); // error! pw's type is Widget*, but
// update takes a SpecialWidget*
<A NAME="78326"></A>
update(const_cast<SpecialWidget*>(pw));
// error! const_cast can be used only
// to affect constness or volatileness,
// never to cast down the inheritance
// hierarch
</PRE>
</UL>
<A NAME="78335"></A>
<P><A NAME="dingp12"></A>
By far the most common use of <CODE>const_cast</CODE> is to cast away the <CODE>const</CODE>ness of an <NOBR>object.<SCRIPT>create_link(12);</SCRIPT>
</NOBR></P><A NAME="78401"></A>
<A NAME="p14"></A><P><A NAME="dingp13"></A>
The second specialized type of cast, <CODE>dynamic_cast</CODE>, is used to perform <I>safe casts</I> down or across an inheritance hierarchy. That is, you use <CODE>dynamic_cast</CODE> to cast pointers or references to base class objects into pointers or references to derived or sibling base class objects in such a way that you can determine whether the casts succeeded.<a href="#79079"><sup>1</sup></A> Failed casts are indicated by a null pointer (when casting pointers) or an exception (when casting <NOBR>references):<SCRIPT>create_link(13);</SCRIPT>
</NOBR></P><A NAME="78385"></A>
<UL><PRE>Widget *pw;
</PRE>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -