⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eiintro.htm

📁 一个非常适合初学者入门的有关c++的文档
💻 HTM
📖 第 1 页 / 共 3 页
字号:
  strcpy(data, rhs.data);

  return *this;                            // see <A HREF="./EI15_FR.HTM#2182" TARGET="_top">Item&nbsp;15</A>
}
</PRE>
</UL>

<P><A NAME="dingp36"></A><A NAME="1767"></A>
Notice how the constructor must check its parameter for validity and how it must take pains to ensure that the member <CODE>data</CODE> is properly initialized, i.e., points to a <CODE>char*</CODE> that is properly null-terminated. On the other hand, the assignment operator takes it for granted that its parameter is legitimate. Instead, it concentrates on detecting pathological conditions, such as assignment to itself (see <A HREF="./EI17_FR.HTM#2264" TARGET="_top">Item 17</A>), and on deallocating old memory before allocating new memory. The differences between these two functions typify the differences between object initialization and object assignment. By the way, if the "<CODE>[]</CODE>" notation in the use of <CODE>delete</CODE> is new to you (pardon the pun), Items <A HREF="EI5_FR.HTM#1869" TARGET="_top">5</A> and <A HREF="../MEC/MI8_FR.HTM#33985" TARGET="_top">M8</A> should dispel any confusion you may <NOBR>have.<SCRIPT>create_link(36);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp37"></A><A NAME="1768"></A>
A final term that warrants discussion is <I>client</I>. A client is a programmer, one who uses the code you write. When I talk about clients in this book, I am referring to people looking at your code, trying to figure out what it does; to people reading your class definitions, attempting to determine whether they want to inherit from your classes; to people examining your design decisions, hoping to glean insights into their <NOBR>rationale.<SCRIPT>create_link(37);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp38"></A><A NAME="1769"></A>
You may not be used to thinking about your clients, but I'll spend a good deal of time trying to convince you to make their lives as easy as you can. After all, you are a client of the software other people develop. Wouldn't you want those people to make things easy for you? Besides, someday you may find yourself in the uncomfortable position of having to use your <i>own</i> code, in which case your client will be <NOBR>you!<SCRIPT>create_link(38);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp39"></A><A NAME="13076"></A>
I use two constructs in this book that may not be familiar to you. Both are relatively recent additions to C++. The first is the <CODE>bool</CODE> type, which has as its values the keywords <CODE>true</CODE> and <CODE>false</CODE>. This is the type now <A NAME="p10"></A>returned by the built-in relational operators (e.g., <CODE>&lt;</CODE>, <CODE>&gt;</CODE>, <CODE>==</CODE>, etc.) and tested in the condition part of <CODE>if</CODE>, <CODE>for</CODE>, <CODE>while</CODE>, and <CODE>do</CODE> statements. If your compilers haven't implemented <CODE>bool</CODE>, an easy way to approximate it is to use a typedef for <CODE>bool</CODE> and constant objects for <CODE>true</CODE> and <CODE>false</CODE>:<SCRIPT>create_link(39);</SCRIPT>
</P>

<UL><A NAME="13058"></A>
<PRE>typedef int bool;
</PRE><A NAME="13059"></A>
<PRE>const bool false = 0;
const bool true = 1;
</PRE>
</UL>

<P><A NAME="dingp40"></A><A NAME="13060"></A>
This is compatible with the traditional semantics of C and C++. The behavior
of programs using this approximation won't change when they're ported to
<CODE>bool</CODE>-supporting compilers. For a different way of approximating
<CODE>bool</CODE> &#151; including a discussion of the advantages and
disadvantages of each approach &#151; turn to the <A
HREF="../MEC/MIINTRFR.HTM#71736" TARGET="_top">Introduction of <i>More
Effective C++</i></A>.<SCRIPT>create_link(40);</SCRIPT>
</P>

<P><A NAME="dingp41"></A><A NAME="13062"></A>
The second new construct is really four constructs, the casting forms <CODE>static_cast</CODE>, <CODE>const_cast</CODE>, <CODE>dynamic_cast</CODE>, and <CODE>reinterpret_cast</CODE>. Conventional C-style casts look like <NOBR>this:<SCRIPT>create_link(41);</SCRIPT>
</NOBR></P>

<UL><A NAME="13120"></A>
<PRE>(<i>type</i>) <i>expression</i>                           // cast <i>expression</i> to be of
                                            // type <i>type</i>
</PRE>
</UL><A NAME="13119"></A>
<A NAME="dingp42"></A><P>
The new casts look like <NOBR>this:<SCRIPT>create_link(42);</SCRIPT>
</NOBR></P>
<UL><A NAME="13123"></A>
<PRE>static_cast&lt;type&gt;(<i>expression</i>)               // cast <i>expression</i> to be of
                                            // type <i>type</i>
const_cast&lt;type&gt;(<i>expression</i>)
</PRE><A NAME="13125"></A>
<PRE>dynamic_cast&lt;type&gt;(<i>expression</i>)      &lt;type&gt;
</PRE><A NAME="13126"></A>
<PRE>reinterpret_cast&lt;type&gt;(<i>expression</i>)  &lt;type&gt;
</PRE>
</UL>

<P><A NAME="dingp43"></A><A NAME="13117"></A>
These different casting forms serve different <NOBR>purposes:<SCRIPT>create_link(43);</SCRIPT>
</NOBR></P>

<UL><A NAME="20220"></A>
<A NAME="dingp44"></A><LI><CODE>const_cast</CODE> is designed to cast away the constness of objects and pointers, a topic I examine in <A HREF="./EI21_FR.HTM#6003" TARGET="_top">Item 21</A>.<SCRIPT>create_link(44);</SCRIPT>

<A NAME="20221"></A>
<A NAME="dingp45"></A><LI><CODE>dynamic_cast</CODE> is used to perform "safe downcasting," a subject we'll explore in <A HREF="./EI39_FR.HTM#7269" TARGET="_top">Item 39</A>.<SCRIPT>create_link(45);</SCRIPT>

<A NAME="20223"></A>
<A NAME="dingp46"></A><LI><CODE>reinterpret_cast</CODE> is engineered for casts that yield implementation-dependent results, e.g., casting between function pointer types. (You're not likely to need <CODE>reinterpret_cast</CODE> very often. I don't use it at all in this book.)<SCRIPT>create_link(46);</SCRIPT>

<A NAME="20225"></A>
<A NAME="dingp47"></A><LI><CODE>static_cast</CODE> is sort of the catch-all cast. It's what you use when none of the other casts is appropriate. It's the closest in meaning to the conventional C-style casts.<SCRIPT>create_link(47);</SCRIPT>

</UL>

<P><A NAME="dingp48"></A><A NAME="13151"></A>
Conventional casts continue to be legal, but the new casting forms are preferable. They're much easier to identify in code (both for humans and for tools like <CODE>grep</CODE>), and the more narrowly specified purpose of each casting form makes it possible for compilers to diagnose usage er<A NAME="p11"></A>rors. For example, only <CODE>const_cast</CODE> can be used to cast away the constness of something. If you try to cast away an object's or a pointer's constness using one of the other new casts, your cast expression won't <NOBR>compile.<SCRIPT>create_link(48);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp49"></A><A NAME="13287"></A>
For more information on the new casts, see <A HREF="../MEC/MI2_FR.HTM#77216" TARGET="_top">Item M2</A> or consult a recent introductory textbook on <NOBR>C++.<SCRIPT>create_link(49);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp50"></A><A NAME="1770"></A>
In the code examples in this book, I have tried to select meaningful names for objects, classes, functions, etc. Many books, when choosing identifiers, embrace the time-honored adage that brevity is the soul of wit, but I'm not as interested in being witty as I am in being clear. I have therefore striven to break the tradition of using cryptic identifiers in books on programming languages. Nonetheless, I have at times succumbed to the temptation to use two of my favorite parameter names, and their meanings may not be immediately apparent, especially if you've never done time on a compiler-writing chain <NOBR>gang.<SCRIPT>create_link(50);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp51"></A><A NAME="1771"></A>
The names are <CODE>lhs</CODE> and <CODE>rhs</CODE>, and they stand for "left-hand side" and "right-hand side," respectively. I use them as parameter names for functions implementing binary operators, especially <CODE>operator==</CODE> and arithmetic operators like <CODE>operator*</CODE>. For example, if <CODE>a</CODE> and <CODE>b</CODE> are objects representing rational numbers, and if rational numbers can be multiplied via a non-member <CODE>operator*</CODE> function, the <NOBR>expression<SCRIPT>create_link(51);</SCRIPT>
</NOBR></P>

<UL><A NAME="1772"></A>
<PRE>a * b
</PRE>
</UL><A NAME="1773"></A>
is equivalent to the function call
<UL><A NAME="1774"></A>
<PRE>operator*(a, b)
</PRE>
</UL>

<P><A NAME="dingp52"></A><A NAME="1775"></A>
As you will discover in <A HREF="./EI23_FR.HTM#6210" TARGET="_top">Item 23</A>, I declare <CODE>operator*</CODE> like <NOBR>this:<SCRIPT>create_link(52);</SCRIPT>
</NOBR></P>

<UL><A NAME="1776"></A>
<PRE>const Rational operator*(const Rational&amp; lhs,
                         const Rational&amp; rhs);
</PRE>
</UL>

<P><A NAME="dingp53"></A><A NAME="1777"></A>
As you can see, the left-hand operand, <CODE>a</CODE>, is known as <CODE>lhs</CODE> inside the function, and the right-hand operand is known as <CODE>rhs</CODE>.<SCRIPT>create_link(53);</SCRIPT>
</P>

<P><A NAME="dingp54"></A><A NAME="12642"></A>
I've also chosen to abbreviate names for pointers according to this rule: a pointer to an object of type <CODE>T</CODE> is often called <CODE>pt</CODE>, "pointer to T." Here are some <NOBR>examples:<SCRIPT>create_link(54);</SCRIPT>
</NOBR></P>

<UL><A NAME="12643"></A>
<PRE>string *ps;                               // ps = ptr to string
</PRE><A NAME="1780"></A>
<PRE>class Airplane;
Airplane *pa;                             // pa = ptr to Airplane
</PRE><A NAME="1781"></A>
<PRE>class BankAccount;
BankAccount *pba;                         // pba = ptr to BankAccount
</PRE>
</UL>

<P><A NAME="dingp55"></A><A NAME="1782"></A>
<A NAME="p12"></A><A NAME=""></A>I use a similar convention for references. That is, <CODE>rs</CODE> might be a reference-to-<CODE>string</CODE> and <CODE>ra</CODE> a reference-to-<CODE>Airplane</CODE>.<SCRIPT>create_link(55);</SCRIPT>
</P>

<P><A NAME="dingp56"></A><A NAME="2263"></A>
I occasionally use the name <CODE>mf</CODE> when I'm talking about member <NOBR>functions.<SCRIPT>create_link(56);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp57"></A><A NAME="2215"></A>
On the off chance there might be some confusion, any time I mention the C programming language in this book, I mean the <NOBR><FONT COLOR="#FF0000" SIZE="-2"><B>&deg;</B></FONT><A HREF="http://www.awl.com/cseng/cgi-bin/cdquery.pl?name=iso " onMouseOver="self.status='ISO'; return true" onMouseOut="self.status = self.defaultStatus" TARGET="_top">ISO</A>/<NOBR><NOBR><FONT COLOR="#FF0000" SIZE="-2"><B>&deg;</B></FONT><A HREF="http://www.awl.com/cseng/cgi-bin/cdquery.pl?name=ansi " onMouseOver="self.status='ANSI'; return true" onMouseOut="self.status = self.defaultStatus" TARGET="_top">ANSI</A></NOBR>-sanctified version of C, not the older, less strongly-typed, "classic" <NOBR>C.<SCRIPT>create_link(57);</SCRIPT>
</NOBR></P>

<DIV ALIGN="CENTER"><FONT SIZE="-1">Back to <A HREF="./EIACK_FR.HTM" TARGET="_top">Acknowledgments</A> &nbsp;&nbsp;<BR>&nbsp;&nbsp;Continue to <A HREF="./ESHIFTFR.HTM" TARGET="_top">Shifting from C to C++</A></FONT></DIV>
<HR WIDTH="100%">
<A NAME="dingp58"></A><A NAME="2"><sup>3</sup>
     My <code>String</code>抯 constructor taking a <code>const char*</code>
     argument handles the case where a null pointer is passed in, but the
     standard <code>string</code> type is not required to be so tolerant.
     Attempts to create a <code>string</code> from a null pointer yield
     undefined results. However, it is safe to create a <code>string</code>
     object from an empty <code>char*</code>-based string, i.e., from
     "".<SCRIPT>create_link(58);</SCRIPT>
<BR><A HREF="#1">Return</A>
</BODY>
</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -