📄 ei50.htm
字号:
<A NAME="25546"></A>
<P><A NAME="dingp15"></A>
<A NAME="p235"></A>As I said, <I>The Design and Evolution of C++</I> is fine for insights into the language's design, and the standard is great for nailing down language details, but it would be nice if there were a comfortable middle ground between D&E's view from 10,000 meters and the standard's micron-level examination. Textbooks are supposed to fill this niche, but they generally drift toward the standard's perspective, whereby <i>what</i> the language is receives a lot more attention than <i>why</i> it's that <NOBR>way.<SCRIPT>create_link(15);</SCRIPT>
</NOBR></P>
<A NAME="25650"></A>
<P><A NAME="dingp16"></A>
Enter the ARM. The ARM is another book, <NOBR><FONT COLOR="#FF0000" SIZE="-2"><B>°</B></FONT><A HREF="http://www.awl.com/cseng/cgi-bin/cdquery.pl?name=anncrm" onMouseOver = "self.status = 'The Annotated C++ Reference Manual Home Page'; return true" onMouseOut = "self.status = self.defaultStatus" TARGET="_top"><I>The</NOBR> Annotated C++ Reference Manual</I></A>, by Margaret Ellis and <NOBR><FONT COLOR="#FF0000" SIZE="-2"><B>°</B></FONT><A HREF="http://www.awl.com/cseng/cgi-bin/cdquery.pl?name=bjarne" onMouseOver = "self.status = 'Bjarne Stroustrup'; return true" onMouseOut = "self.status = self.defaultStatus" TARGET="_top">Bjarne</NOBR> Stroustrup</A> (Addison-Wesley, 1990). Upon its publication, it became <i>the</i> authority on C++, and the international standard started with the ARM (along with the existing C standard) as its basis. In the intervening years, the language specified by the standard has in some ways parted company with that described by the ARM, so the ARM is no longer the authority it once was. It's still a useful reference, however, because most of what it says is still true, and it's not uncommon for vendors to adhere to the ARM specification in areas of C++ where the standard has only recently settled <NOBR>down.<SCRIPT>create_link(16);</SCRIPT>
</NOBR></P>
<A NAME="25776"></A>
<P><A NAME="dingp17"></A>
What makes the ARM really useful, however, isn't the RM part (the Reference Manual), it's the A part: the annotations. The ARM provides extensive commentary on <I>why</I> many features of C++ behave the way they do. Some of this information is in D&E, but much of it isn't, and you <I>do</I> want to know it. For instance, here's something that drives most people crazy when they first encounter <NOBR>it:<SCRIPT>create_link(17);</SCRIPT>
</NOBR></P>
<A NAME="8581"></A>
<UL><PRE>class Base {
public:
virtual void f(int x);
};
class Derived: public Base {
public:
virtual void f(double *pd);
};
Derived *pd = new Derived;
pd->f(10); // error!
</PRE>
</UL><A NAME="8582"></A>
<P><A NAME="dingp18"></A>
The problem is that <CODE>Derived::f</CODE> hides <CODE>Base::f</CODE>, even though they take different parameter types, so compilers demand that the call to <CODE>f</CODE> take a <CODE>double*</CODE>, which the literal <CODE>10</CODE> most certainly is <NOBR>not.<SCRIPT>create_link(18);</SCRIPT>
</NOBR></P>
<A NAME="8583"></A>
<P><A NAME="dingp19"></A>
This is inconvenient, but the ARM provides an explanation for this behavior. Suppose that when you called <CODE>f</CODE>, you really did want to call the version in <CODE>Derived</CODE>, but you accidentally used the wrong parameter type. Further suppose that <CODE>Derived</CODE> is way down in an inheritance hi<A NAME="p236"></A>erarchy and that you were unaware that <CODE>Derived</CODE> indirectly inherits from some base class <CODE>BaseClass</CODE>, and that <CODE>BaseClass</CODE> declares a virtual function <CODE>f</CODE> that takes an <CODE>int</CODE>. In that case, you would have inadvertently called <CODE>BaseClass::f</CODE>, a function you didn't even know existed! This kind of error could occur frequently where large class hierarchies are used, so Stroustrup decided to nip it in the bud by having derived class members hide base class members on a per-name <NOBR>basis.<SCRIPT>create_link(19);</SCRIPT>
</NOBR></P>
<A NAME="223014"></A>
<P><A NAME="dingp20"></A>
Note, by the way, that if the writer of <CODE>Derived</CODE> wants to allow clients to access <CODE>Base::f</CODE>, this is easily accomplished via a simple <CODE>using</CODE> <NOBR>declaration:<SCRIPT>create_link(20);</SCRIPT>
</NOBR></P>
<A NAME="223016"></A>
<UL><PRE>class Derived: public Base {
public:
using Base::f; // import Base::f into
// Derived's scope
virtual void f(double *pd);
};
Derived *pd = new Derived;
pd->f(10); // fine, calls Base::f
</PRE>
</UL><A NAME="223017"></A>
<P><A NAME="dingp21"></A>
For compilers not yet supporting <CODE>using</CODE> declarations, an alternative is to employ an inline <NOBR>function:<SCRIPT>create_link(21);</SCRIPT>
</NOBR></P>
<A NAME="223019"></A>
<UL><PRE>class Derived: public Base {
public:
virtual void f(int x) { Base::f(x); }
virtual void f(double *pd);
};
Derived *pd = new Derived;
pd->f(10); // fine, calls Derived::f(int),
// which calls Base::f(int)
</PRE>
</UL><A NAME="8587"></A>
<P><A NAME="dingp22"></A>
Between D&E and the ARM, you'll gain insights into the design and implementation of C++ that make it possible to appreciate the sound, no-nonsense architecture behind a sometimes baroque-looking facade. Fortify those insights with the detailed information in the standard, and you've got a foundation for software development that leads to truly <I>effective</I> <NOBR>C++.<SCRIPT>create_link(22);</SCRIPT>
</NOBR></P>
<DIV ALIGN="CENTER"><FONT SIZE="-1">Back to <A HREF="EI49_FR.HTM" TARGET="_top">Item 49: Familiarize yourself with the standard library.</A> <BR> Continue to <A HREF="./EIAFTRFR.HTM" TARGET="_top">Afterword</A></DIV></FONT>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -