📄 mi2.htm
字号:
</UL><A NAME="78391"></A>
<UL><PRE>...
</PRE>
</UL><A NAME="78390"></A>
<UL><PRE>update(dynamic_cast<SpecialWidget*>(pw));
// fine, passes to update a pointer
// to the SpecialWidget pw points to
// if pw really points to one,
// otherwise passes the null pointer
</PRE>
</UL><A NAME="78423"></A>
<UL><PRE>void updateViaRef(SpecialWidget& rsw);
</PRE>
</UL><A NAME="78870"></A>
<UL><PRE>updateViaRef(dynamic_cast<SpecialWidget&>(*pw));
// fine, passes to updateViaRef the
// SpecialWidget pw points to if pw
// really points to one, otherwise
// throws an exception
</PRE>
</UL><A NAME="79012"></A>
<P><A NAME="dingp14"></A>
<CODE>dynamic_cast</CODE>s are restricted to helping you navigate inheritance hierarchies. They cannot be applied to types lacking virtual functions (see also <a href="./MI24_FR.HTM#41284" target="_top">Item 24</A>), nor can they cast away <CODE>const</CODE>ness:<SCRIPT>create_link(14);</SCRIPT>
</P><A NAME="78958"></A>
<UL><PRE>int firstNumber, secondNumber;
...
double result = dynamic_cast<double>(firstNumber)/secondNumber;
// error! no inheritance is involved
</PRE>
</UL><A NAME="78967"></A>
<UL><PRE>const SpecialWidget sw;
...
update(dynamic_cast<SpecialWidget*>(&sw));
// error! dynamic_cast can't cast
// away constness
</PRE>
</UL><A NAME="78774"></A>
<P><A NAME="dingp15"></A>
If you want to perform a cast on a type where inheritance is not involved, you probably want a <CODE>static_cast</CODE>. To cast <CODE>const</CODE>ness away, you always want a <CODE>const_cast</CODE>.<SCRIPT>create_link(15);</SCRIPT>
</P><A NAME="79074"></A>
<P><A NAME="dingp16"></A>
The last of the four new casting forms is <CODE>reinterpret_cast</CODE>. This operator is used to perform type conversions whose result is nearly always implementation-defined. As a result, <CODE>reinterpret_cast</CODE>s are rarely <NOBR>portable.<SCRIPT>create_link(16);</SCRIPT>
</NOBR></P><A NAME="78457"></A>
<A NAME="p15"></A><P><A NAME="dingp17"></A>
The most common use of <CODE>reinterpret_cast</CODE> is to cast between function pointer types. For example, suppose you have an array of pointers to functions of a particular <NOBR>type:<SCRIPT>create_link(17);</SCRIPT>
</NOBR></P><A NAME="78458"></A>
<UL><PRE>typedef void (*FuncPtr)(); // a FuncPtr is a pointer
// to a function taking no
// args and returning void
</PRE>
</UL><A NAME="78459"></A>
<UL><PRE>FuncPtr funcPtrArray[10]; // funcPtrArray is an array
// of 10 FuncPtrs
</PRE>
</UL><A NAME="78460"></A>
<P><A NAME="dingp18"></A>
Let us suppose you wish (for some unfathomable reason) to place a pointer to the following function into <CODE>funcPtrArray</CODE>:<SCRIPT>create_link(18);</SCRIPT>
</P><A NAME="78461"></A>
<UL><PRE>int doSomething();
</PRE>
</UL><A NAME="78475"></A>
<P><A NAME="dingp19"></A>
You can't do what you want without a cast, because <CODE>doSomething</CODE> has the wrong type for <CODE>funcPtrArray</CODE>. The functions in <CODE>funcPtrArray</CODE> return <CODE>void</CODE>, but <CODE>doSomething</CODE> returns an <CODE>int</CODE>:<SCRIPT>create_link(19);</SCRIPT>
</P><A NAME="78479"></A>
<UL><PRE>funcPtrArray[0] = &doSomething; // error! type mismatch
</PRE>
</UL><A NAME="78481"></A>
<P><A NAME="dingp20"></A>
A <CODE>reinterpret_cast</CODE> lets you force compilers to see things your <NOBR>way:<SCRIPT>create_link(20);</SCRIPT>
</NOBR></P><A NAME="78486"></A>
<UL><PRE>funcPtrArray[0] = // this compiles
reinterpret_cast<FuncPtr>(&doSomething);
</PRE>
</UL><A NAME="78437"></A>
<P><A NAME="dingp21"></A>
Casting function pointers is not portable (C++ offers no guarantee that all function pointers are represented the same way), and in some cases such casts yield incorrect results (see <a href="./MI31_FR.HTM#34883" TARGET="_top">Item 31</A>), so you should avoid casting function pointers unless your back's to the wall and a knife's at your throat. A sharp knife. A <I>very</I> sharp <NOBR>knife.<SCRIPT>create_link(21);</SCRIPT>
</NOBR></P><A NAME="77203"></A>
<P><A NAME="dingp22"></A>
If your compilers lack support for the new casting forms, you can use traditional casts in place of <CODE>static_cast</CODE>, <CODE>const_cast</CODE>, and <CODE>reinterpret_cast</CODE>. Furthermore, you can use macros to approximate the new <NOBR>syntax:<SCRIPT>create_link(22);</SCRIPT>
</NOBR></P><A NAME="78698"></A>
<UL><PRE>#define static_cast(TYPE,EXPR) ((TYPE)(EXPR))
#define const_cast(TYPE,EXPR) ((TYPE)(EXPR))
#define reinterpret_cast(TYPE,EXPR) ((TYPE)(EXPR))
</PRE>
</UL><A NAME="78719"></A>
<P><A NAME="dingp23"></A>
You'd use the approximations like <NOBR>this:<SCRIPT>create_link(23);</SCRIPT>
</NOBR></P><A NAME="78727"></A>
<UL><PRE>double result = static_cast(double, firstNumber)/secondNumber;
</PRE>
</UL><A NAME="78707"></A>
<UL><PRE>update(const_cast(SpecialWidget*, &sw));
</PRE>
</UL><A NAME="78735"></A>
<UL><PRE>funcPtrArray[0] = reinterpret_cast(FuncPtr, &doSomething);
</PRE>
</UL><A NAME="81227"></A>
<P><A NAME="dingp24"></A>
These approximations won't be as safe as the real things, of course, but they will simplify the process of upgrading your code when your compilers support the new <NOBR>casts.<SCRIPT>create_link(24);</SCRIPT>
</NOBR></P><A NAME="78697"></A>
<A NAME="p16"></A><P><A NAME="dingp25"></A>
There is no easy way to emulate the behavior of a <CODE>dynamic_cast</CODE>, but many libraries provide functions to perform safe inheritance-based casts for you. If you lack such functions and you <I>must</I> perform this type of cast, you can fall back on C-style casts for those, too, but then you forego the ability to tell if the casts fail. Needless to say, you can define a macro to look like <CODE>dynamic_cast</CODE>, just as you can for the other <NOBR>casts:<SCRIPT>create_link(25);</SCRIPT>
</NOBR></P><A NAME="81220"></A>
<UL><PRE>#define dynamic_cast(TYPE,EXPR) (TYPE)(EXPR)
</PRE>
</UL><A NAME="81269"></A>
<P><A NAME="dingp26"></A>
Remember that this approximation is not performing a true <CODE>dynamic_cast</CODE>; there is no way to tell if the cast <NOBR>fails.<SCRIPT>create_link(26);</SCRIPT>
</NOBR></P><A NAME="84816"></A>
<P><A NAME="dingp27"></A>
I know, I know, the new casts are ugly and hard to type. If you find them too unpleasant to look at, take solace in the knowledge that C-style casts continue to be valid. However, what the new casts lack in beauty they make up for in precision of meaning and easy recognizability. Programs that use the new casts are easier to parse (both for humans and for tools), and they allow compilers to diagnose casting errors that would otherwise go undetected. These are powerful arguments for abandoning C-style casts, and there may also be a third: perhaps making casts ugly and hard to type is a <I>good</I> <NOBR>thing.<SCRIPT>create_link(27);</SCRIPT>
</NOBR></P>
<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>
<HR>
<A NAME="dingp28"></A>
<sup>1</sup><A NAME="79079"></A> A second, unrelated use of <CODE>dynamic_cast</CODE> is to find the beginning of the memory occupied by an object. We explore that capability in <a href="./MI27_FR.HTM" TARGET="_top">Item 27</A>.<SCRIPT>create_link(28);</SCRIPT>
<BR>
<A HREF="#78401">Return</A>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -