<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>默然前行</title>
    <description>我喜欢、热爱这门语言。 她是我最好的情人。
                                         --送给C++
</description>
    <link>http://shi5jin.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>站在巨人肩上的思考[连载] （8）</title>
        <author>shi5jin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shi5jin.javaeye.com">shi5jin</a>&nbsp;
          链接：<a href="http://shi5jin.javaeye.com/blog/145604" style="color:red;">http://shi5jin.javaeye.com/blog/145604</a>&nbsp;
          发表时间: 2007年12月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          &nbsp;
<h3><span lang="EN-US">5.2 </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">数组</span></h3>
<h4><span lang="EN-US">5.2.2 </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Cambria; mso-hansi-font-family: Cambria; mso-fareast-font-family: 宋体; mso-ascii-theme-font: major-latin; mso-fareast-theme-font: major-fareast; mso-hansi-theme-font: major-latin">字符串文字量</span></h4>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">类似</span><span lang="EN-US">&rdquo;this is a string.&rdquo;</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">这样一个字符串文字量，它是一个常量。正如代码中一个显式的数字</span><span lang="EN-US">0xff08</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">一样，其值不可以被更改。如想修改，可以通过复制给一个变量来实现：</span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span lang="EN-US"><v:shapetype o:spt="202" coordsize="21600,21600" id="_x0000_t202" path="m,l,21600r21600,l21600,xe"><v:stroke joinstyle="miter"></v:stroke><v:path o:connecttype="rect" gradientshapeok="t"></v:path></v:shapetype><v:shape strokecolor="#95b3d7" id="_x0000_s1034" type="#_x0000_t202" strokeweight="1pt" style="WIDTH: 374.2pt; HEIGHT: 36.05pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line; mso-width-relative: margin; mso-height-relative: margin"><v:fill focusposition="1" focus="100%" focussize="" type="gradient" color2="#b8cce4"></v:fill><v:shadow offset2="-3pt" color="#243f60" type="perspective" on="t" opacity=".5" offset="1pt"></v:shadow><v:textbox>
<table cellspacing="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td>
            <div>
            <p class="MsoNormal"><span lang="EN-US">int a = 0xff08;</span></p>
            <p class="MsoNormal"><span lang="EN-US">a = 0xff18;</span></p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</v:textbox><w:wrap type="none"></w:wrap><w:anchorlock></w:anchorlock></v:shape><v:shapetype o:spt="75" coordsize="21600,21600" filled="f" stroked="f" id="_x0000_t75" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" o:connecttype="rect" gradientshapeok="t"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">对于字符串文字量则有一点要注意：</span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span lang="EN-US"><v:shape strokecolor="#95b3d7" id="_x0000_s1033" type="#_x0000_t202" strokeweight="1pt" style="WIDTH: 374.2pt; HEIGHT: 72.85pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line; mso-width-relative: margin; mso-height-relative: margin"><v:fill focusposition="1" focus="100%" focussize="" type="gradient" color2="#b8cce4"></v:fill><v:shadow offset2="-3pt" color="#243f60" type="perspective" on="t" opacity=".5" offset="1pt"></v:shadow><v:textbox>
<table cellspacing="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td>
            <div>
            <p class="MsoNormal"><span lang="EN-US">char* cp = &ldquo;this is a string&rdquo;;<span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">危险！赋值给一个普通字符指针；</span></p>
            <p class="MsoNormal"><span lang="EN-US">cp[4] = &lsquo;e&rsquo;; <span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">未定义行为！不能给常量赋值；</span></p>
            <p class="MsoNormal"><span lang="EN-US">char p[] = &ldquo;this is a string&rdquo;;<span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">可以；</span></p>
            <p class="MsoNormal"><span lang="EN-US">p[4] = &lsquo;e&rsquo;;<span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">正确执行；</span></p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</v:textbox><w:wrap type="none"></w:wrap><w:anchorlock></w:anchorlock></v:shape></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">可以看出，用</span><span lang="EN-US">char *</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">来引用字符串文字量是一个十分危险的地方。在上例中</span><span lang="EN-US">cp[4]=&rsquo;e&rsquo;;</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">可以通过编译，但是在执行期间产生了一个</span><span lang="EN-US">Segmentation Fault</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">。也就是说编译器并不能帮助程序员发现这类错误。</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">我个人是这样认为的：字符串文字量是一中很底层的数据，编译器把他放进汇编语言中的数据段；普通的</span><span lang="EN-US">char*</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">指针也是一种很底层的指针，他可以指向内存空间中的任何地址；</span><span lang="EN-US">char* cp = &ldquo;this is a string&rdquo;;</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">仅仅在栈空间生成一个指针，然后把他指向位于数据段的</span><span lang="EN-US">&rdquo;this is a string&rdquo;</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">，初始化并不会导致错误。但是利用</span><span lang="EN-US">cp[4]</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">更改数据段中的数据内容将会导致段错误，数据段是只读的。而利用</span><span lang="EN-US">char p[]</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">形式的时候，意味着将在栈空间中生成一个字符数组，然后用</span><span lang="EN-US">&rdquo;this is a string&rdquo;</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">来进行初始化，而后</span><span lang="EN-US">p</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">指向这个栈空间中字符数组的首地址。此时</span><span lang="EN-US">p[4]=&rsquo;e&rsquo;;</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">修改的是栈空间中的值，而不是数据段中的值。</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">但是</span><span lang="EN-US">p</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">是什么类型呢？是</span><span lang="EN-US">char*</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">么？他的大小是多少？是</span><span lang="EN-US">1</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">么？为了使指针和数组首地址之间的区别更具普遍意义，我们用</span><span lang="EN-US">int</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">类型来测试一下：</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span lang="EN-US"><v:shape strokecolor="#95b3d7" id="_x0000_s1032" type="#_x0000_t202" strokeweight="1pt" style="WIDTH: 374.2pt; HEIGHT: 104.65pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line; mso-width-relative: margin; mso-height-relative: margin"><v:fill focusposition="1" focus="100%" focussize="" type="gradient" color2="#b8cce4"></v:fill><v:shadow offset2="-3pt" color="#243f60" type="perspective" on="t" opacity=".5" offset="1pt"></v:shadow><v:textbox>
<table cellspacing="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td>
            <div>
            <p class="MsoNormal"><span lang="EN-US">char p[] = &quot;hello&quot;;</span></p>
            <p class="MsoNormal"><span lang="EN-US">char* ptr = p;</span></p>
            <p class="MsoNormal"><span lang="EN-US">cout &lt;&lt; sizeof(p) &lt;&lt; &quot;:&quot; &lt;&lt; sizeof(*p) &lt;&lt; endl;</span></p>
            <p class="MsoNormal"><span lang="EN-US">cout &lt;&lt; p &lt;&lt; &quot;:&quot; &lt;&lt; *p &lt;&lt; endl;</span></p>
            <p class="MsoNormal"><span lang="EN-US">cout &lt;&lt; sizeof(ptr) &lt;&lt; &quot;:&quot; &lt;&lt; sizeof(*ptr) &lt;&lt; endl;</span></p>
            <p class="MsoNormal"><span lang="EN-US">cout &lt;&lt; ptr &lt;&lt; &quot;:&quot; &lt;&lt; *ptr &lt;&lt; endl;</span></p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</v:textbox><w:wrap type="none"></w:wrap><w:anchorlock></w:anchorlock></v:shape></span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">这段代码在我的电脑上的输出是：</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span lang="EN-US"><v:shape strokecolor="#f2f2f2 [3041]" fillcolor="black [3200]" id="_x0000_s1031" type="#_x0000_t202" strokeweight="3pt" style="WIDTH: 374.2pt; HEIGHT: 87.2pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line; mso-width-relative: margin; mso-height-relative: margin"><v:shadow offset2="-1pt" color="#7f7f7f [1601]" type="perspective" on="t" opacity=".5" offset="1pt"></v:shadow><v:textbox style="mso-next-textbox: #_x0000_s1031">
<table cellspacing="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td>
            <div>
            <p class="MsoNormal"><span lang="EN-US">[/home/gavin/test]# ./test</span></p>
            <p class="MsoNormal"><span lang="EN-US">6:1</span></p>
            <p class="MsoNormal"><span lang="EN-US">hello:h</span></p>
            <p class="MsoNormal"><span lang="EN-US">4:1</span></p>
            <p class="MsoNormal"><span lang="EN-US">hello:h</span></p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</v:textbox><w:wrap type="none"></w:wrap><w:anchorlock></w:anchorlock></v:shape></span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span lang="EN-US">ptr</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">是真正的</span><span lang="EN-US">char*</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">类型，其</span><span lang="EN-US">sizeof</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">是</span><span lang="EN-US">4</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">，但是</span><span lang="EN-US">p</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的</span><span lang="EN-US">sizeof</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">却是</span><span lang="EN-US">6</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">，也就是</span><span lang="EN-US">&rdquo;hello&rdquo;</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">加一个&lsquo;</span><span lang="EN-US">\0</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">&rsquo;的长度。除此之外，</span><span lang="EN-US">ptr</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">和</span><span lang="EN-US">p</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">表现都一样。但我们最好认为</span><span lang="EN-US">p</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">是字符数组类型，而</span><span lang="EN-US">ptr</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">才是字符指针类型，因为他们的行为上存在差异。很多教师、教材都说：&ldquo;数组名就是指向数组首地址的指针。&rdquo;这其实并不完全正确。</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">再仔细看看，我们</span><span lang="EN-US">cout&lt;&lt;p</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">和</span><span lang="EN-US">cout&lt;&lt;ptr</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的期望输出应该是</span><span lang="EN-US">p</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">和</span><span lang="EN-US">ptr</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">分别表示的地址。但事实上却是数组的内容。为了明显区分，再看下面这段代码：</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span lang="EN-US"><v:shape strokecolor="#95b3d7" id="_x0000_s1030" type="#_x0000_t202" strokeweight="1pt" style="WIDTH: 374.2pt; HEIGHT: 104.65pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line; mso-width-relative: margin; mso-height-relative: margin"><v:fill focusposition="1" focus="100%" focussize="" type="gradient" color2="#b8cce4"></v:fill><v:shadow offset2="-3pt" color="#243f60" type="perspective" on="t" opacity=".5" offset="1pt"></v:shadow><v:textbox>
<table cellspacing="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td>
            <div>
            <p class="MsoNormal"><span lang="EN-US">int arr[4] = {0};</span></p>
            <p class="MsoNormal"><span lang="EN-US">int* pa = arr;</span></p>
            <p class="MsoNormal"><span lang="EN-US">cout &lt;&lt; sizeof(arr) &lt;&lt; &quot;:&quot; &lt;&lt; sizeof(*arr) &lt;&lt; endl;</span></p>
            <p class="MsoNormal"><span lang="EN-US">cout &lt;&lt; arr &lt;&lt; &quot;:&quot; &lt;&lt; *arr &lt;&lt; endl;</span></p>
            <p class="MsoNormal"><span lang="EN-US">cout &lt;&lt; sizeof(pa) &lt;&lt; &quot;:&quot; &lt;&lt; sizeof(*pa) &lt;&lt; endl;</span></p>
            <p class="MsoNormal"><span lang="EN-US">cout &lt;&lt; pa &lt;&lt; &quot;:&quot; &lt;&lt; *pa &lt;&lt; endl;</span></p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</v:textbox><w:wrap type="none"></w:wrap><w:anchorlock></w:anchorlock></v:shape></span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">在我的电脑上输出为：</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span lang="EN-US"><v:shape strokecolor="#f2f2f2" fillcolor="black" id="_x0000_s1029" type="#_x0000_t202" strokeweight="3pt" style="WIDTH: 374.2pt; HEIGHT: 87.2pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line; mso-width-relative: margin; mso-height-relative: margin"><v:shadow offset2="-1pt" color="#7f7f7f" type="perspective" on="t" opacity=".5" offset="1pt"></v:shadow><v:textbox style="mso-next-textbox: #_x0000_s1029">
<table cellspacing="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td>
            <div>
            <p class="MsoNormal"><span lang="EN-US">[/home/gavin/test]# ./test </span></p>
            <p class="MsoNormal"><span lang="EN-US">16:4</span></p>
            <p class="MsoNormal"><span lang="EN-US">0xbfc26e5c:0</span></p>
            <p class="MsoNormal"><span lang="EN-US">4:4</span></p>
            <p class="MsoNormal"><span lang="EN-US">0xbfc26e5c:0</span></p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</v:textbox><w:wrap type="none"></w:wrap><w:anchorlock></w:anchorlock></v:shape></span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span lang="EN-US">sizeof</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的输出刚才已经说过。这里可以看出，</span><span lang="EN-US">int</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">数组名和</span><span lang="EN-US">char</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">数组名的行为也不一样。事实上，</span><span lang="EN-US">cha</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">数组名与标准类型数组名的行为都不一样。这也就是为什么</span><span lang="EN-US">C</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">风格字符串为许多人诟病的地方。</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">在这方面提供了很好的改进：用一种更上层的类型</span><span lang="EN-US">string</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">来代替</span><span lang="EN-US">C</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">风格字符串。并强烈建议程序员在程序中尽量使用</span><span lang="EN-US">string</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">来代替</span><span lang="EN-US">char *</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">。这里是你需要做出选择的地方：</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span lang="EN-US"><v:shape strokecolor="#95b3d7" id="_x0000_s1028" type="#_x0000_t202" strokeweight="1pt" style="WIDTH: 374.2pt; HEIGHT: 180.35pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line; mso-width-relative: margin; mso-height-relative: margin"><v:fill focusposition="1" focus="100%" focussize="" type="gradient" color2="#b8cce4"></v:fill><v:shadow offset2="-3pt" color="#243f60" type="perspective" on="t" opacity=".5" offset="1pt"></v:shadow><v:textbox>
<table cellspacing="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td>
            <div>
            <p class="MsoNormal"><span lang="EN-US">string str1(&quot;1&quot;);</span></p>
            <p class="MsoNormal"><span lang="EN-US">string str2(&quot;1234567&quot;);</span></p>
            <p class="MsoNormal"><span lang="EN-US">string str3(&quot;1234567890123456789012345678901234567890&quot;);</span></p>
            <p class="MsoNormal"><span lang="EN-US">/*</span></p>
            <p class="MsoNormal"><span lang="EN-US">char str1[] = &quot;1&quot;;</span></p>
            <p class="MsoNormal"><span lang="EN-US">char str2[] = &quot;1234567&quot;;</span></p>
            <p class="MsoNormal"><span lang="EN-US">char str3[] = &quot;1234567890123456789012345678901234567890&quot;;</span></p>
            <p class="MsoNormal"><span lang="EN-US">*/</span></p>
            <p class="MsoNormal"><span lang="EN-US">cout &lt;&lt; sizeof(str1) &lt;&lt; endl;</span></p>
            <p class="MsoNormal"><span lang="EN-US">cout &lt;&lt; sizeof(str2) &lt;&lt; endl;</span></p>
            <p class="MsoNormal"><span lang="EN-US">cout &lt;&lt; sizeof(str3) &lt;&lt; endl;</span></p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</v:textbox><w:wrap type="none"></w:wrap><w:anchorlock></w:anchorlock></v:shape></span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">当利用</span><span lang="EN-US">C</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">风格字符串的输出为：</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span lang="EN-US"><v:shape strokecolor="#f2f2f2" fillcolor="black" id="_x0000_s1027" type="#_x0000_t202" strokeweight="3pt" style="WIDTH: 374.2pt; HEIGHT: 123pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line; mso-width-relative: margin; mso-height-relative: margin; mso-left-percent: -10001; mso-top-percent: -10001; mso-position-horizontal: absolute; mso-position-vertical: absolute"><v:shadow offset2="-1pt" color="#7f7f7f" type="perspective" on="t" opacity=".5" offset="1pt"></v:shadow><v:textbox style="mso-next-textbox: #_x0000_s1027">
<table cellspacing="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td>
            <div>
            <p class="MsoNormal"><span lang="EN-US">[/home/gavin/test]# ./test </span></p>
            <p class="MsoNormal"><span lang="EN-US">2</span></p>
            <p class="MsoNormal"><span lang="EN-US">8</span></p>
            <p class="MsoNormal"><span lang="EN-US">41</span></p>
            <p class="MsoNormal"><span lang="EN-US">[/home/gavin/test]# ls -l</span></p>
            <p class="MsoNormal"><span lang="EN-US">-rwxrwxr-x 1 863 863<span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>6559 Dec<span style="mso-spacerun: yes">&nbsp; </span>3 14:29 test</span></p>
            <p class="MsoNormal"><span lang="EN-US">-rw-rw-r-- 1 863 863<span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp; </span>391 Dec<span style="mso-spacerun: yes">&nbsp; </span>3 14:29 test.cpp</span></p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</v:textbox><w:wrap type="none"></w:wrap><w:anchorlock></w:anchorlock></v:shape></span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">而当使用</span><span lang="EN-US">string</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">时：</span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span lang="EN-US"><v:shape strokecolor="#f2f2f2" fillcolor="black" id="_x0000_s1026" type="#_x0000_t202" strokeweight="3pt" style="WIDTH: 374.2pt; HEIGHT: 123pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line; mso-width-relative: margin; mso-height-relative: margin; mso-left-percent: -10001; mso-top-percent: -10001; mso-position-horizontal: absolute; mso-position-vertical: absolute"><v:shadow offset2="-1pt" color="#7f7f7f" type="perspective" on="t" opacity=".5" offset="1pt"></v:shadow><v:textbox style="mso-next-textbox: #_x0000_s1026">
<table cellspacing="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td>
            <div>
            <p class="MsoNormal"><span lang="EN-US">[/home/gavin/test]# ./test </span></p>
            <p class="MsoNormal"><span lang="EN-US">4</span></p>
            <p class="MsoNormal"><span lang="EN-US">4</span></p>
            <p class="MsoNormal"><span lang="EN-US">4</span></p>
            <p class="MsoNormal"><span lang="EN-US">[/home/gavin/test]# ls -l</span></p>
            <p class="MsoNormal"><span lang="EN-US">-rwxrwxr-x 1 863 863<span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>7578 Dec<span style="mso-spacerun: yes">&nbsp; </span>3 14:30 test</span></p>
            <p class="MsoNormal"><span lang="EN-US">-rw-rw-r-- 1 863 863<span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp; </span>390 Dec<span style="mso-spacerun: yes">&nbsp; </span>3 14:30 test.cpp</span></p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</v:textbox><w:wrap type="none"></w:wrap><w:anchorlock></w:anchorlock></v:shape></span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">我们也许可以得到如下结论：</span><span lang="EN-US">sting</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">比</span><span lang="EN-US">char[]</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">需要更少的运行时内存空间，但是</span><span lang="EN-US">char[]</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">却比</span><span lang="EN-US">string</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">占用更少的磁盘空间。你可以自己选择向左还是向右走。不过相比</span><span lang="EN-US">string</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的易用性、安全性、以及诸多的成员函数带来的实用功能来说，我个人并不认为</span><span lang="EN-US">char[]</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">节省的磁盘空间是很突出的优点。</span></p>
          <br/>
          <span style="color:red;">
            <a href="http://shi5jin.javaeye.com/blog/145604#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 03 Dec 2007 14:58:01 +0800</pubDate>
        <link>http://shi5jin.javaeye.com/blog/145604</link>
        <guid>http://shi5jin.javaeye.com/blog/145604</guid>
      </item>
      <item>
        <title>站在巨人肩上的思考[连载] （7）</title>
        <author>shi5jin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shi5jin.javaeye.com">shi5jin</a>&nbsp;
          链接：<a href="http://shi5jin.javaeye.com/blog/145603" style="color:red;">http://shi5jin.javaeye.com/blog/145603</a>&nbsp;
          发表时间: 2007年12月03日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          &nbsp;
<h3><a name="_Toc184196889"><span lang="EN-US">4.8 </span></a><span style="mso-bookmark: _Toc184196889"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">枚举</span></span></h3>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">枚举是表示具有共同属性的整型常量集合的用户自定义类型。这其中包含这些含义：</span></p>
<p class="MsoNormal" style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1"><span lang="EN-US" style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri"><span style="mso-list: Ignore">1.<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">枚举的取值只能是整数，正负皆可；</span></p>
<p class="MsoNormal" style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1"><span lang="EN-US" style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri"><span style="mso-list: Ignore">2.<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">枚举的取值是常量，枚举初始化后，这些值不能被改变；</span></p>
<p class="MsoNormal" style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1"><span lang="EN-US" style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri"><span style="mso-list: Ignore">3.<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">枚举也是一种用户自定义类型，用户定义好枚举后，可以自定义该枚举类型自身的操作，如&ldquo;</span><span lang="EN-US">++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">&rdquo;，&ldquo;</span><span lang="EN-US">&lt;&lt;&rdquo;</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">等；</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">枚举类型的取值隐含着这样的&ldquo;潜规则&rdquo;：</span></p>
<p class="MsoNormal" style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt; mso-list: l1 level1 lfo2"><span lang="EN-US" style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><span style="mso-list: Ignore">l<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">如果枚举中所有枚举值均非负，那么该枚举表示的范围，是包含这些枚举值的所有</span><span lang="EN-US">[0, 2<sup>k</sup>-1]</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">区间中最小的那个；</span></p>
<p class="MsoNormal" style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt; mso-list: l1 level1 lfo2"><span lang="EN-US" style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><span style="mso-list: Ignore">l<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">如果枚举中包含负枚举值，那么该枚举表示的范围，是包含这些枚举值的所有</span><span lang="EN-US">[-2<sup>k</sup>, 2<sup>k</sup>-1]</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">区间中最小的那个；</span></p>
<p class="MsoNormal" style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt; mso-list: l1 level1 lfo2"><span lang="EN-US" style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><span style="mso-list: Ignore">l<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">枚举的</span><span lang="EN-US">sizeof</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">，就是某个能容纳其范围的整型的</span><span lang="EN-US">sizeof</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">，但不会大于</span><span lang="EN-US">sizeof(int)</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">；</span></p>
<p class="MsoNormal" style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt; mso-list: l1 level1 lfo2"><span lang="EN-US" style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><span style="mso-list: Ignore">l<span style="FONT: 7pt 'Times New Roman'">&nbsp; </span></span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">如果不显式的复制，那么默认枚举值将从</span><span lang="EN-US">0</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">开始递增；</span></p>
<p class="MsoNormal" style="MARGIN-LEFT: 21pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">例如：</span></p>
<p class="MsoNormal" style="MARGIN-LEFT: 21pt"><span lang="EN-US"><v:shapetype o:spt="202" coordsize="21600,21600" id="_x0000_t202" path="m,l,21600r21600,l21600,xe"><v:stroke joinstyle="miter"></v:stroke><v:path o:connecttype="rect" gradientshapeok="t"></v:path></v:shapetype><v:shape strokecolor="#95b3d7" id="_x0000_s1027" type="#_x0000_t202" strokeweight="1pt" style="WIDTH: 374.2pt; HEIGHT: 75.7pt; mso-height-percent: 200; mso-position-horizontal-relative: char; mso-position-vertical-relative: line; mso-width-relative: margin; mso-height-relative: margin"><v:fill focusposition="1" focus="100%" focussize="" type="gradient" color2="#b8cce4"></v:fill><v:shadow offset2="-3pt" color="#243f60" type="perspective" on="t" opacity=".5" offset="1pt"></v:shadow><v:textbox style="mso-fit-shape-to-text: t">
<table cellspacing="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td>
            <div>
            <p class="MsoNormal"><span lang="EN-US">enum Flags { A=1, B=2, C=9</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">，</span><span lang="EN-US">D=7};<span style="mso-spacerun: yes">&nbsp; </span>//Flags</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的取值范围是</span><span lang="EN-US">[0, 15]</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">；</span></p>
            <p class="MsoNormal"><span lang="EN-US">Flags f1 = 5;<span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">错误！没有定义从</span><span lang="EN-US">int</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">到</span><span lang="EN-US">Flags</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的隐式类型转换；</span></p>
            <p class="MsoNormal" style="MARGIN-LEFT: 105pt; TEXT-INDENT: -105pt; mso-char-indent-count: -10.0"><span lang="EN-US">Flags f2 = Flags(14);<span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">可以，利用显式的类型转换，而且</span><span lang="EN-US">14</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">在</span><span lang="EN-US">[0,15]</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">中；</span></p>
            <p class="MsoNormal" style="TEXT-INDENT: 105pt; mso-char-indent-count: 10.0"><span lang="EN-US">//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">虽然在</span><span lang="EN-US">Flags</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的定义当中没有</span><span lang="EN-US">14</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">这个值；</span></p>
            <p class="MsoNormal"><span lang="EN-US">Flags f3 = Flags(21)</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">；</span><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp;&nbsp; </span>//</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">错误！</span><span lang="EN-US">21</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">不在</span><span lang="EN-US">[0, 15]</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">当中；</span></p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</v:textbox><w:wrap type="none"></w:wrap><w:anchorlock></w:anchorlock></v:shape><v:shapetype o:spt="75" coordsize="21600,21600" filled="f" stroked="f" id="_x0000_t75" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" o:connecttype="rect" gradientshapeok="t"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype></span></p>
<p class="MsoNormal" style="MARGIN-LEFT: 21pt"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<h2><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Cambria; mso-hansi-font-family: Cambria">第</span><span lang="EN-US">5</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Cambria; mso-hansi-font-family: Cambria">章</span> <span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Cambria; mso-hansi-font-family: Cambria">指针、数组和结构</span></h2>
<h3><span lang="EN-US">5.1 </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">指针</span></h3>
<h4><span lang="EN-US">5.1.1 </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Cambria; mso-hansi-font-family: Cambria; mso-fareast-font-family: 宋体; mso-ascii-theme-font: major-latin; mso-fareast-theme-font: major-fareast; mso-hansi-theme-font: major-latin">零</span></h4>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span class="MsoIntenseEmphasis"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">&ldquo;由于各种标准转换，</span><span lang="EN-US">0</span></span><span class="MsoIntenseEmphasis"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">可以被用于作为任意整型、浮点类型、指针、还有指向成员的指针的常量。&rdquo;</span></span><a href="http://shi5jin.javaeye.com/javascripts/fckeditor/editor/fckeditor.html?InstanceName=message&amp;Toolbar=Topic#_ftn1" name="_ftnref1" title="" style="mso-footnote-id: ftn1"><span class="MsoFootnoteReference"><strong><em><span lang="EN-US" style="COLOR: #4f81bd"><span style="mso-special-character: footnote"><span class="MsoFootnoteReference"><strong style="mso-bidi-font-weight: normal"><span lang="EN-US" style="FONT-SIZE: 10.5pt; COLOR: #4f81bd; FONT-FAMILY: 'Calibri','sans-serif'; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: 宋体; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">[1]</span></strong></span></span></span></em></strong></span></a><span class="MsoIntenseEmphasis"><span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="TEXT-INDENT: 21pt"><span class="MsoIntenseEmphasis"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">&ldquo;</span><span lang="EN-US">0</span></span><span class="MsoIntenseEmphasis"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的类型将由上下文确定&rdquo;</span></span><a href="http://shi5jin.javaeye.com/javascripts/fckeditor/editor/fckeditor.html?InstanceName=message&amp;Toolbar=Topic#_ftn2" name="_ftnref2" title="" style="mso-footnote-id: ftn2"><span class="MsoFootnoteReference"><strong><em><span lang="EN-US" style="COLOR: #4f81bd"><span style="mso-special-character: footnote"><span class="MsoFootnoteReference"><strong style="mso-bidi-font-weight: normal"><span lang="EN-US" style="FONT-SIZE: 10.5pt; COLOR: #4f81bd; FONT-FAMILY: 'Calibri','sans-serif'; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: 宋体; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">[2]</span></strong></span></span></span></em></strong></span></a><span class="MsoIntenseEmphasis"><span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">为更好的保证类型安全，建议在</span><span lang="EN-US">C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">中用</span><span lang="EN-US">0</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">代替所有的</span><span lang="EN-US">NULL</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">。如果不得不使用</span><span lang="EN-US">NULL</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">，那么用下面的妥协方案：</span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span lang="EN-US"><v:shape strokecolor="#95b3d7" id="_x0000_s1026" type="#_x0000_t202" strokeweight="1pt" style="WIDTH: 374.2pt; HEIGHT: 70.85pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line; mso-width-relative: margin; mso-height-relative: margin"><v:fill focusposition="1" focus="100%" focussize="" type="gradient" color2="#b8cce4"></v:fill><v:shadow offset2="-3pt" color="#243f60" type="perspective" on="t" opacity=".5" offset="1pt"></v:shadow><v:textbox>
<table cellspacing="0" width="100%" cellpadding="0">
    <tbody>
        <tr>
            <td>
            <div>
            <p class="MsoNormal"><span lang="EN-US">#ifndef _DEF_NULL_</span></p>
            <p class="MsoNormal"><span lang="EN-US">#define _DEF_NULL_</span></p>
            <p class="MsoNormal"><span lang="EN-US">const int NULL = 0;</span></p>
            <p class="MsoNormal"><span lang="EN-US">#endif</span></p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</v:textbox><w:wrap type="none"></w:wrap><w:anchorlock></w:anchorlock></v:shape></span></p>
<div style="mso-element: footnote-list"><br clear="all" />
<hr size="1" align="left" width="33%" />
<div id="ftn1" style="mso-element: footnote">
<p class="MsoFootnoteText"><a href="http://shi5jin.javaeye.com/javascripts/fckeditor/editor/fckeditor.html?InstanceName=message&amp;Toolbar=Topic#_ftnref1" name="_ftn1" title="" style="mso-footnote-id: ftn1"><span class="MsoFootnoteReference"><span lang="EN-US"><span style="mso-special-character: footnote"><span class="MsoFootnoteReference"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 'Calibri','sans-serif'; mso-fareast-font-family: 宋体; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">[1]</span></span></span></span></span></a><span lang="EN-US"> </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">《</span><span lang="EN-US">The C++ Programming Language</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">》</span><span lang="EN-US">-- Chapter 5.1.1, paragraph 1</span></p>
</div>
<div id="ftn2" style="mso-element: footnote">
<p class="MsoFootnoteText"><a href="http://shi5jin.javaeye.com/javascripts/fckeditor/editor/fckeditor.html?InstanceName=message&amp;Toolbar=Topic#_ftnref2" name="_ftn2" title="" style="mso-footnote-id: ftn2"><span class="MsoFootnoteReference"><span lang="EN-US"><span style="mso-special-character: footnote"><span class="MsoFootnoteReference"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 'Calibri','sans-serif'; mso-fareast-font-family: 宋体; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">[2]</span></span></span></span></span></a><span lang="EN-US"> </span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">《</span><span lang="EN-US">The C++ Programming Language</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">》</span><span lang="EN-US">-- Chapter 5.1.1, paragraph 1</span></p>
</div>
</div>
          <br/>
          <span style="color:red;">
            <a href="http://shi5jin.javaeye.com/blog/145603#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 03 Dec 2007 14:56:08 +0800</pubDate>
        <link>http://shi5jin.javaeye.com/blog/145603</link>
        <guid>http://shi5jin.javaeye.com/blog/145603</guid>
      </item>
      <item>
        <title>一种“标准”的虚函数机制简介</title>
        <author>shi5jin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shi5jin.javaeye.com">shi5jin</a>&nbsp;
          链接：<a href="http://shi5jin.javaeye.com/blog/139424" style="color:red;">http://shi5jin.javaeye.com/blog/139424</a>&nbsp;
          发表时间: 2007年11月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          &nbsp;&nbsp;&nbsp; 编译器是如何针对<a href="javascript:;" onclick="javascript:tagshow(event, '%D0%E9%BA%AF%CA%FD');" target="_self"><u><strong>虚函数</strong></u></a>产生可以再运行时刻确定被调用函数的代码呢？也就是说，虚函数实际上是如何被编译器处理的呢？Lippman在深度探索C++对象模型中的不同章节讲到了几种方式，这里把&ldquo;标准的&rdquo;方式简单介绍一下。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;我所说的&ldquo;标准&rdquo;方式，也就是所谓的&ldquo;VTABLE&rdquo;机制。编译器发现一个类中有被声明为virtual的函数，就会为其搞一个虚函数表，也就是VTABLE。<u>VTABLE实际上是一个函数指针的数组</u>，每个虚函数占用这个数组的一个slot。<u>一个类只有一个VTABLE</u>，不管它有多少个实例。派生类有自己的VTABLE，但是<u>派生类的VTABLE与基类的VTABLE有相同的函数排列顺序</u>，同名的虚函数被放在两个数组的相同位置上。在创建类实例的时候，编译器还会在每个实例的内存布局中增加一个vptr字段，该字段指向本类的VTABLE。通过这些手段，编译器在看到一个虚函数调用的时候，就会将这个调用改写，针对1.1中的例子：<br />
<br />
void bar(A * a)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;a-&gt;foo();<br />
}<br />
<br />
会被改写为：<br />
<br />
void bar(A * a)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;(a-&gt;vptr[1])();<br />
}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;因为派生类和基类的foo()函数具有相同的VTABLE索引，而他们的vptr又指向不同的VTABLE，因此通过这样的方法可以在运行时刻决定调用哪个foo()函数。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;虽然实际情况远非这么简单，但是基本原理大致如此。<br />
          <br/>
          <span style="color:red;">
            <a href="http://shi5jin.javaeye.com/blog/139424#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 09 Nov 2007 11:07:00 +0800</pubDate>
        <link>http://shi5jin.javaeye.com/blog/139424</link>
        <guid>http://shi5jin.javaeye.com/blog/139424</guid>
      </item>
      <item>
        <title>“界面”使用的情况</title>
        <author>shi5jin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shi5jin.javaeye.com">shi5jin</a>&nbsp;
          链接：<a href="http://shi5jin.javaeye.com/blog/131091" style="color:red;">http://shi5jin.javaeye.com/blog/131091</a>&nbsp;
          发表时间: 2007年10月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          现有一基础模块A，提供模块间通信服务。类B、C中都有一个私有A*成员用于与其他模块之间通信，B、C的构造函数要求提供一个A的指针来初始化该私有成员。使用B的开发人员在平台W1上开发程序P1，具有A的A1实现版本；使用C的开发人员在平台W2上开发程序P2，具有A的A2实现版本；P1，P2进行通信。现在来看看A的界面如何使用：<br />
<br />
对于A的设计者，给出A的界面接口规范A.h向所有驱动厂商、用户提供；并且给出了W1平台的实现A1.h，A1.cpp，其中A1中有派生类A1 : public A，并在A1.cpp中给出了全部接口实现；编译出A1库，并且向客户提供头文件A1.h；<br />
<br />
类B为使用A，在B的接口规范B.h中包含A.h，定义A*私有成员，并通过构造函数获得一个A*；B.cpp的所有实现都对A*进行操作。<br />
类C也是这样。<br />
<br />
开发P1的程序员在自己定义的模块中需要包含B.h来使用B，其所在的W1中使用的是A的A1版本，故在头文件中应该：<br />
<div class="code_title">cpp 代码</div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-cpp">
    <li class="alt"><span><span class="comment">////P1.h</span><span>&nbsp;&nbsp;</span></span> </li>
    <li class=""><span><span class="preprocessor">#include&nbsp;&quot;B.h&quot;</span><span>&nbsp;&nbsp;</span></span> </li>
    <li class="alt"><span><span class="preprocessor">#include&nbsp;&quot;A1.h&quot;</span><span>&nbsp;&nbsp;</span></span> </li>
    <li class=""><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>A1*&nbsp;a1ptr&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;A1(...);&nbsp;&nbsp;</span></span> </li>
    <li class=""><span>B&nbsp;&nbsp;b(a1ptr);&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>b.fun()&nbsp;&nbsp;</span> </li>
    <li class=""><span>...&nbsp;&nbsp;</span> </li>
</ol>
</div>
而开发P2的程序员，首先根据A.h开发自己的A的实现A2.h, A2.cpp，然后在自己的模块中使用A2：<br />
<div class="code_title">cpp 代码</div>
<div class="dp-highlighter">
<div class="bar">&nbsp;</div>
<ol class="dp-cpp">
    <li class="alt"><span><span class="comment">////P2.h&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span></span> </li>
    <li class=""><span><span class="preprocessor">&nbsp;#include&nbsp;&quot;C.h&quot;&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span></span> </li>
    <li class="alt"><span><span class="preprocessor">&nbsp;#include&nbsp;&quot;A2.h&quot;&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span></span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;A2*&nbsp;a2ptr&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;A2(...);&nbsp;&nbsp;&nbsp;&nbsp;</span></span> </li>
    <li class=""><span>&nbsp;C&nbsp;&nbsp;c(a2ptr);&nbsp;&nbsp;&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;c.fun()&nbsp;&nbsp;&nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;...&nbsp;&nbsp;&nbsp;</span> </li>
</ol>
</div>
<p>这样，A的开发人员可以根据不同环境，开发不同的驱动版本A1， A2， ....；而这些A的不同实现，并不影响B、C的设计和实现人员；P1、P2的开发人员可以根据自己实际需要选择A的不同实现（或者根据A.h自己再开发），而应用B，C。<br />
<br />
另外一个好处是更换A的驱动，并不需要重新编译B、C，只需要重新编译P1，P2，并重新链接B、C即可。结构如下图：<br />
<img src="file:///C:/DOCUME~1/user/LOCALS~1/Temp/moz-screenshot-1.jpg" alt="" /></p>
<p>带箭头的线表示继承关系，带实心球的线表示包含关系。<br />
</p>
          <br/>
          <span style="color:red;">
            <a href="http://shi5jin.javaeye.com/blog/131091#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 11 Oct 2007 15:46:37 +0800</pubDate>
        <link>http://shi5jin.javaeye.com/blog/131091</link>
        <guid>http://shi5jin.javaeye.com/blog/131091</guid>
      </item>
      <item>
        <title>shell 快速变量处理</title>
        <author>shi5jin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shi5jin.javaeye.com">shi5jin</a>&nbsp;
          链接：<a href="http://shi5jin.javaeye.com/blog/123743" style="color:red;">http://shi5jin.javaeye.com/blog/123743</a>&nbsp;
          发表时间: 2007年09月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <span class="tpc_content"><font size="2">　　Bash Shell可以进行变量的条件替换,既只有某种条件发生时才进行替换,替换<br />
条件放在{}中.<br />
(1) ${value:-word}<br />
当变量未定义或者值为空时,返回值为word的内容,否则返回变量的值.<br />
(2) ${value:=word}<br />
与前者类似,只是若变量未定义或者值为空时,在返回word的值的同时将<br />
word赋值给value<br />
(3) ${value:?message}<br />
若变量以赋值的话,正常替换.否则将消息message送到标准错误输出(若<br />
此替换出现在Shell程序中,那么该程序将终止运行)<br />
(4) ${value:+word}<br />
若变量以赋值的话,其值才用word替换,否则不进行任何替换<br />
(5) ${value:offset}<br />
${value:offset:length}<br />
从变量中提取子串,这里offset和length可以是算术表达式.<br />
(6) ${#value}<br />
变量的字符个数 (变量的字符个数，并不是变量个数）<br />
(7) ${value#pattern}<br />
${value##pattern}<br />
去掉value中与pattern相匹配的部分,条件是value的开头与pattern相匹配<br />
#与##的区别在于一个是最短匹配模式,一个是最长匹配模式.<br />
(8) ${value%pattern}<br />
${value%%pattern}<br />
于(7)类似,只是是从value的尾部于pattern相匹配,%与%%的区别与#与##一样<br />
(9) ${value/pattern/string}<br />
${value//pattern/string}<br />
进行变量内容的替换,把与pattern匹配的部分替换为string的内容,/与//的区<br />
别与上同<br />
<br />
注意:上述条件变量替换中,除(2)外,其余均不影响变量本身的值</font></span>
          <br/>
          <span style="color:red;">
            <a href="http://shi5jin.javaeye.com/blog/123743#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 14 Sep 2007 11:10:06 +0800</pubDate>
        <link>http://shi5jin.javaeye.com/blog/123743</link>
        <guid>http://shi5jin.javaeye.com/blog/123743</guid>
      </item>
      <item>
        <title>A Generic Ostream Iterator</title>
        <author>shi5jin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shi5jin.javaeye.com">shi5jin</a>&nbsp;
          链接：<a href="http://shi5jin.javaeye.com/blog/121560" style="color:red;">http://shi5jin.javaeye.com/blog/121560</a>&nbsp;
          发表时间: 2007年09月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          by Christopher Diggins<br />
November 11, 2005<br />
<br />
&nbsp;&nbsp;&nbsp; Summary<br />
&nbsp;&nbsp;&nbsp; Ostream iterators are a handy but under-utilized tool for using the STL to output containers and ranges. Here I provide an alternative, which has a more pleasing syntax. <br />
<hr size="2" width="100%" />
An ostream iterator, allows you to use STL algorithms, such as std::copy to output a container or range to an output stream. A simple example is:<br />
<br />
int main() {<br />
&nbsp; int array[] = { 1, 2, 4, 8, 16, 32, 64 };<br />
&nbsp; std::copy(array, array + 7, std::ostream_iterator&lt;int&gt;(std::cout, &quot;\n&quot;));<br />
}<br />
<br />
The declaration for an ostream_iterator is clunky because you to know the kind of elements it will be reading. You can make the code more readable as follows:<br />
<br />
int main() {<br />
&nbsp; int array[] = { 1, 2, 4, 8, 16, 32, 64 };<br />
&nbsp; typedef std::ostream_iterator&lt;int&gt; oiter;<br />
&nbsp; std::copy(array, array + 7, oiter(std::cout, &quot;\n&quot;));<br />
}<br />
<br />
This is still more complex than strictly neccessary. The problem is that the ostream_iterator is a template. An alternative implementation would be to make the operator=() member function a template.<br />
<br />
#include &lt;iostream&gt;<br />
<br />
struct putter {<br />
&nbsp; putter(const putter&amp; x) : o(x.o), delim(x.delim) { }<br />
&nbsp; putter(std::ostream&amp; x = std::cout, const char* s = &quot;&quot;) : o(x), delim(s) { }<br />
&nbsp; template&lt;typename T&gt;<br />
&nbsp; putter&amp; operator=(const T&amp; x) { o &lt;&lt; x &lt;&lt; delim; return *this; }<br />
&nbsp; putter&amp; operator*() { return *this; }<br />
&nbsp; putter&amp; operator++() { return *this; }<br />
&nbsp; putter&amp; operator++(int) { return *this; }<br />
&nbsp; mutable std::ostream&amp; o;<br />
&nbsp; const char* delim;<br />
};<br />
<br />
putter put(std::ostream&amp; o = std::cout, const char* delim = &quot;&quot;) {<br />
&nbsp; return putter(o, delim);<br />
}<br />
<br />
Now you can output the contents of any iterator pair with less work.<br />
<br />
int main() {<br />
&nbsp; int array[] = { 1, 2, 4, 8, 16, 32, 64 };<br />
&nbsp; std::copy(array, array + 7, put(std::cout, &quot;\n&quot;));<br />
}<br />
          <br/>
          <span style="color:red;">
            <a href="http://shi5jin.javaeye.com/blog/121560#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 07 Sep 2007 08:37:30 +0800</pubDate>
        <link>http://shi5jin.javaeye.com/blog/121560</link>
        <guid>http://shi5jin.javaeye.com/blog/121560</guid>
      </item>
      <item>
        <title>我能从构造函数调用虚函数吗？</title>
        <author>shi5jin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shi5jin.javaeye.com">shi5jin</a>&nbsp;
          链接：<a href="http://shi5jin.javaeye.com/blog/121214" style="color:red;">http://shi5jin.javaeye.com/blog/121214</a>&nbsp;
          发表时间: 2007年09月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div><font size="3"><font face="Verdana">可以。不过你得悠着点。当你这样做时，也许你自己都不知道自己在干什么！在构造函数中，虚拟机制尚未发生作用，因为此时overriding尚未发生。万丈高楼平地起，总得先打地基吧？对象的建立也是这样&mdash;&mdash;先把基类构造完毕，然后在此基础上构造派生类。</font></font></div>
<div>&nbsp;</div>
<div><font size="3" face="Verdana">看看这个例子：</font></div>
<pre><font size="3" color="#000080" face="Verdana">	#include<strong>&lt;</strong>string<strong>&gt;</strong><br />	#include<strong>&lt;</strong>iostream<strong>&gt;</strong><br />	using namespace std;<br /><br />	class B {<br />	public:<br />		B(const string&amp; ss) { cout &lt;&lt; &quot;B constructor\n&quot;; f(ss); }<br />		virtual void f(const string&amp;) { cout &lt;&lt; &quot;B::f\n&quot;;}<br />	};<br /><br />	class D : public B {<br />	public:<br />		D(const string &amp; ss) :B(ss) { cout &lt;&lt; &quot;D constructor\n&quot;;}<br />		void f(const string&amp; ss) { cout &lt;&lt; &quot;D::f\n&quot;; s = ss; }<br />	private:<br />		string s;<br />	};<br /><br />	int main()<br />	{<br />		D d(&quot;Hello&quot;);<br />	}<br /></font></pre>
<div>&nbsp;</div>
<div><font size="3" face="Verdana">这段程序经编译运行，得到这样的结果：</font></div>
<pre><font size="3" color="#000080" face="Verdana">	B constructor<br />	<strong>B::f</strong><br />	D constructor</font></pre>
<pre><font size="3" face="Verdana">注意，输出<strong>不是D::f </strong>。 究竟发生了什么？f()是在B::B()中调用的。如果构造函数中调用虚函数的规则不是如前文所述那样，<br />而是如一些人希望的那样去调用D::f()。那么因为构造函数D::D()尚未运行，字符串s还未初始化，所以当D::f()试图将参数<br />赋给s时，结果多半是&mdash;&mdash;立马当机。</font></pre>
<p><font size="3" face="Verdana">析构则正相反，遵循从继承类到基类的顺序（拆房子总得从上往下拆吧？），所以其调用虚函数的行为和在构造函数中一样：虚函数<strong>此时此刻</strong>被绑定到哪里（当然应该是基类啦&mdash;&mdash;因为继承类已经被&ldquo;拆&rdquo;了&mdash;&mdash;析构了！），调用的就是哪个函数。 </font> </p>
<p><font size="3" face="Verdana">更多细节请见《The Design and Evolution of C++》，13.2.4.2 或者《The C++ Programming Language》第三版，15.4.3 。 </font> </p>
<p><font size="3" face="Verdana">有时，这条规则被解释为是由于编译器的实作造成的。<font color="#0000ff">[译注：从实作角度可以这样解释：在许多编译器中，直到构造函数调用完毕，vtable才被建立，此时虚函数才被动态绑定至继承类的同名函数。]</font> 但事实上不是这么一回事&mdash;&mdash;让编译器实作成&ldquo;构造函数中调用虚函数也和从其他函数中调用一样&rdquo;是很简单的<font color="#0000ff">[译注：只要把vtable的建立移至构造函数调用之前即可]</font>。关键还在于语言设计时的考量&mdash;&mdash;让虚函数可以求助于基类提供的通用代码。<font color="#0000ff">[译注：先有鸡还是先有蛋？Bjarne实际上是在告诉你，不是&ldquo;先有实作再有规则&rdquo;，而是&ldquo;如此实作，因为规则如此&rdquo;。]</font> </font></p>
<p><strong>原文地址：</strong><a href="http://www.research.att.com/%7Ebs/bs_faq2.html#vcall">http://www.research.att.com/~bs/bs_faq2.html#vcall</a></p>
          <br/>
          <span style="color:red;">
            <a href="http://shi5jin.javaeye.com/blog/121214#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 06 Sep 2007 11:18:36 +0800</pubDate>
        <link>http://shi5jin.javaeye.com/blog/121214</link>
        <guid>http://shi5jin.javaeye.com/blog/121214</guid>
      </item>
      <item>
        <title>为何我的构造函数不太对劲？</title>
        <author>shi5jin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shi5jin.javaeye.com">shi5jin</a>&nbsp;
          链接：<a href="http://shi5jin.javaeye.com/blog/121071" style="color:red;">http://shi5jin.javaeye.com/blog/121071</a>&nbsp;
          发表时间: 2007年09月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>&nbsp;类似这样的问题千奇百怪。例如：  </p>
<ul>
    <ul>
        <li>为什么我明明不想复制对象，而编译器却偏偏这么做了呢？  </li>
        <li>如何关闭复制机制？  </li>
        <li>如何防止隐式转换？  </li>
        <li>为何 int 自动转换成了复数？ </li>
    </ul>
</ul>
&nbsp;&nbsp;&nbsp;&nbsp;类的默认复制构造函数和赋值运算符可以复制所有元素。例如：
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct Point {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int x,y;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Point(int xx = 0, int yy = 0) :x(xx), y(yy) { }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Point p1(1,2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Point p2 = p1;  </p>
<p>&nbsp;&nbsp;&nbsp; 至此，p2.x==p1.x 并且 p2.y==p1.y。这可能正是你想要的（而且也是为了和 C 兼容所必需的），但是，以下代码：  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class Handle {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private:<br />
&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;X* p;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handle(string n)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:name(n), p(0) { /* acquire X called &quot;name&quot; and let p point to it */ }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;~Handle() { delete p; /* release X called &quot;name&quot; */ }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// ...<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void f(const string&amp; hh)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handle h1(hh);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handle h1 = h2; // 会引起灾难！<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// ...<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;在此，默认复制构造函数使得 h2.name==h1.name 并且 h2.p==h2.p。这将导致一场灾难：当函数 f() 运行结束时，会调用 h1 和 h2 的析构函数，这就导致 h1.p 和 h2.p 所指向的对象被 delete 了两次。  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;如何避免这场灾难？最简单的办法是，将复制构造函数和赋值运算符声明为私有成员，从而关闭复制机制：  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class Handle {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;X* p;  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handle(const Handle&amp;); // 阻止复制<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handle&amp; operator=(const Handle&amp;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handle(string n)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:name(n), p(0) { /* acquire the X called &quot;name&quot; and let p point to it */ }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;~Handle() { delete p; /* release X called &quot;name&quot; */ }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// ...<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void f(const string&amp; hh)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handle h1(hh);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handle h1 = h2; // 编译器报错<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// ...<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;如果需要复制机制，我们可以定义自己的复制构造函数和赋值运算符，让它们按我们期待的那样工作。  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;现在回过头来再看看类 Point。对 Point 来说，可以使用默认的复制机制，但它的构造函数有点问题：  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct Point {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int x,y;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Point(int xx = 0, int yy = 0) :x(xx), y(yy) { }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void f(Point);  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void g()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Point orig;&nbsp; // 使用默认值 (0,0) 创建 orig&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Point p1(2); // 使用 yy 的默认值 (0) 来创建 p1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f(2);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 调用 Point(2,0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;为了便于创建对象（如这里的 orig 和 p1），我们为 Point 的构造函数提供了默认参数。然后，有些人会感到惊讶的事情发生了：调用 f() 时，2 会转换成 Point(2,0)。当我们定义一个接受单个参数的构造函数时，同时亦定义了一种类型转换方式。默认情况下，类型转换是隐式进行的。若想把类型转换改成 显式进行，就要将构造函数声明为 explicit： </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct Point {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int x,y;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;explicit Point(int xx = 0, int yy = 0) :x(xx), y(yy) { }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void f(Point);  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void g()<br />
&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Point orig;&nbsp;&nbsp; // 使用默认值 (0,0) 创建 orig&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Point p1(2);&nbsp; // 使用 yy 的默认值 (0) 来创建 p1<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 显式调用构造函数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f(2);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 错误（试图进行隐式转换）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Point p2 = 2; // 错误（试图进行隐式转换）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Pont p3 = Point(2); // 正确（显式转换）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}  </p>
<p> </p>
<p><strong>原文地址</strong>：http://www.research.att.com/~bs/bs_faq2.html#explicit-ctor</p>
          <br/>
          <span style="color:red;">
            <a href="http://shi5jin.javaeye.com/blog/121071#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 06 Sep 2007 10:57:38 +0800</pubDate>
        <link>http://shi5jin.javaeye.com/blog/121071</link>
        <guid>http://shi5jin.javaeye.com/blog/121071</guid>
      </item>
      <item>
        <title>如何在类中定义常量？</title>
        <author>shi5jin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shi5jin.javaeye.com">shi5jin</a>&nbsp;
          链接：<a href="http://shi5jin.javaeye.com/blog/121055" style="color:red;">http://shi5jin.javaeye.com/blog/121055</a>&nbsp;
          发表时间: 2007年09月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font size="3"><font face="Verdana"><strong></strong>如果你想得到一个可用于常量表达式中的常量，例如数组大小的定义，那么你有两种选择： </font></font></p>
<pre><font size="3" color="#000080" face="Verdana">	class X {<br /><strong>		static const int c1 = 7;</strong><br /><strong>		enum { c2 = 19 };</strong><br /><br />		char v1[<strong>c1</strong>];<br />		char v2[<strong>c2</strong>];<br /><br />		// ...<br />	};</font></pre>
<pre><font size="3" face="Verdana">一眼望去，c1的定义似乎更加直截了当，但别忘了只有static const的整型或枚举型量才能如此初始化。这就很有局限性，例如：</font></pre>
<pre><font size="3" color="#000080" face="Verdana">	class Y {<br />		const int c3 = 7;		// error: not static<br />		static int c4 = 7;		// error: not const<br />		static const float c5 = 7;	// error not integral<br />	};</font></pre>
<pre><font size="3" face="Verdana">我还是更喜欢玩&ldquo;enum戏法&rdquo;，因为这种定义可移植性好，而且不会引诱我去使用非标准的&ldquo;类内初始化&rdquo;扩展语法。</font></pre>
<p><font size="3" face="Verdana">那么，为何要有这些不方便的限制？因为类通常声明在头文件中，而头文件往往被许多单 元所包含。但是，为了避免链接器设计的复杂化，C++要求每个对象都只能被定义一次。如果C++允许类内定义要作为对象被存在内存中的实体，那么这项要求 就无法满足了。关于C++设计时的一些折衷，参见《<strong><a href="http://www.research.att.com/%7Ebs/dne.html">The Design and Evolution of C++</a></strong>》。 </font> </p>
<p><font size="3" face="Verdana">如果这个常量不需要被用于常量表达式，那么你的选择余地就比较大了： </font></p>
<pre><font color="#000080"><font size="3" face="Verdana">	class Z {<br />		static char* p;		// initialize in definition<br />		const int i;		// initialize in constructor<br />	public:<br />		Z(int ii) :<strong>i(ii)</strong> { }<br />	};<br /><br /></font><strong><font size="3" face="Verdana">	char* Z::p = &quot;hello, there&quot;;<br /></font></strong></font></pre>
<div>&nbsp;</div>
<div><font size="3" face="Verdana">只有当static成员在类外被定义了，你才可以获取它的地址，例如：</font></div>
<pre><font size="3" color="#000080" face="Verdana">	class AE {<br />		// ...<br />	public:<br />		static const int c6 = 7;<br />		static const int c7 = 31;<br />	};<br /><br />	<strong>const int AE::c7;</strong>	// definition<br /><br />	int f()<br />	{<br />		const int* p1 = &amp;AE::c6;	// error: c6 not an lvalue<br />		const int* p2 = &amp;AE::c7;	// ok<br />		// ...<br />	}<br /></font></pre>
<pre><strong>原文地址：</strong><a href="http://www.research.att.com/%7Ebs/bs_faq2.html#in-class">http://www.research.att.com/~bs/bs_faq2.html#in-class</a></pre>
          <br/>
          <span style="color:red;">
            <a href="http://shi5jin.javaeye.com/blog/121055#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 06 Sep 2007 10:51:58 +0800</pubDate>
        <link>http://shi5jin.javaeye.com/blog/121055</link>
        <guid>http://shi5jin.javaeye.com/blog/121055</guid>
      </item>
      <item>
        <title>为何空类的大小不是零？</title>
        <author>shi5jin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shi5jin.javaeye.com">shi5jin</a>&nbsp;
          链接：<a href="http://shi5jin.javaeye.com/blog/120985" style="color:red;">http://shi5jin.javaeye.com/blog/120985</a>&nbsp;
          发表时间: 2007年09月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div><font size="3"><font face="Verdana">为了确保两个不同对象的地址不同，必须如此。也正因为如此，new返回的指针总是指向不同的单个对象。我们还是来看代码吧：</font></font></div>
<pre><font size="3" color="#000080" face="Verdana">	class Empty { };<br /><br />	void f()<br />	{<br />		Empty a, b;<br />		if (&amp;a == &amp;b) cout &lt;&lt; &quot;impossible: report error to compiler supplier&quot;;<br /><br />		Empty* p1 = new Empty;<br />		Empty* p2 = new Empty;<br />		if (p1 == p2) cout &lt;&lt; &quot;impossible: report error to compiler supplier&quot;;<br />	}	<br /></font></pre>
<div>&nbsp;</div>
<div><font size="3" face="Verdana">另外，C++中有一条有趣的规则&mdash;&mdash;空基类并不需要另外一个字节来表示： </font></div>
<pre><font size="3" color="#000080" face="Verdana">	struct X : Empty {<br />		int a;<br />		// ...<br />	};<br /><br />	void f(X* p)<br />	{<br />		void* p1 = p;<br />		void* p2 = &amp;p-&gt;a;<br />		if (p1 == p2) cout &lt;&lt; &quot;nice: good optimizer&quot;;<br />	}<br /></font></pre>
<div>&nbsp;</div>
<div><font size="3" face="Verdana">如果上述代码中p1和p2相等，那么说明编译器作了优化。这样的优化是安全的，而且非常有用。它允许程序员用空类来表示非常简单的概念，而不需为此付出额外的（空间）代价。一些现代编译器提供了这种&ldquo;空基类优化&rdquo;功能。</font></div>
<div>&nbsp;</div>
<div><strong>原文地址：</strong><a href="http://www.research.att.com/%7Ebs/bs_faq2.html#sizeof-empty">http://www.research.att.com/~bs/bs_faq2.html#sizeof-empty</a></div>
          <br/>
          <span style="color:red;">
            <a href="http://shi5jin.javaeye.com/blog/120985#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 06 Sep 2007 10:46:13 +0800</pubDate>
        <link>http://shi5jin.javaeye.com/blog/120985</link>
        <guid>http://shi5jin.javaeye.com/blog/120985</guid>
      </item>
      <item>
        <title>我应该怎样处理内存泄漏？</title>
        <author>shi5jin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shi5jin.javaeye.com">shi5jin</a>&nbsp;
          链接：<a href="http://shi5jin.javaeye.com/blog/120984" style="color:red;">http://shi5jin.javaeye.com/blog/120984</a>&nbsp;
          发表时间: 2007年09月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div><font face="Verdana"><font size="2">很 简单，只要写&ldquo;不漏&rdquo;的代码就完事了啊。显然，如果你的代码到处是new、delete、指针运算，那你想让它&ldquo;不漏&rdquo;都难。不管你有多么小心谨慎，君为 人，非神也，错误在所难免。最终你会被自己越来越复杂的代码逼疯的&mdash;&mdash;你将投身于与内存泄漏的奋斗之中，对bug们不离不弃，直至山峰没有棱角，地球不再 转动。而能让你避免这样困境的技巧也不复杂：你只要倚重隐含在幕后的分配机制&mdash;&mdash;构造和析构，让C++的强大的类系统来助你一臂之力就OK了。标准库中的 那些容器就是很好的实例。它们让你不必化费大量的时间精力也能轻松惬意地管理内存。我们来看看下面的示例代码&mdash;&mdash;设想一下，如果没有了string和 vector，世界将会怎样？如果不用它们，你能第一次就写出毫无内存错误的同样功能代码吗？</font></font></div>
<pre><font size="2" color="#000080" face="Verdana">	#include<strong>&lt;</strong>vector<strong>&gt;</strong><br />	#include<strong>&lt;</strong>string<strong>&gt;</strong><br />	#include<strong>&lt;</strong>iostream<strong>&gt;</strong><br />	#include<strong>&lt;</strong>algorithm<strong>&gt;</strong><br />	using namespace std;<br /><br />	int main()	// small program messing around with strings<br />	{<br />		cout <strong>&lt;&lt;</strong> &quot;enter some whitespace-separated words:\n&quot;;<br />		vector<strong>&lt;</strong>string<strong>&gt;</strong> v;<br />		string s;<br />		while (cin<strong>&gt;&gt;</strong>s) v.push_back(s);<br /><br />		sort(v.begin(),v.end());<br /><br />		string cat;<br />		typedef vector<strong>&lt;</strong>string<strong>&gt;</strong>::const_iterator Iter;<br />		for (Iter p = v.begin(); p!=v.end(); ++p) cat += *p+&quot;+&quot;;<br />		cout <strong>&lt;&lt;</strong> cat <strong>&lt;&lt;</strong> '\n';<br />	}<br /></font></pre>
<p><font size="2" face="Verdana">请注意这里没有显式的内存管理代码。没有宏，没有类型转换，没有溢出检测，没有强制的大小限制，也没有指针。如果使用function  object和标准算法<font color="#0000ff">[译注：指标准库中提供的泛型算法]</font>，我连Iterator也可以不用。不过这毕竟只是一个小程序，杀鸡焉用牛刀？  </font> </p>
<p><font size="2" face="Verdana">当然，这些方法也并非无懈可击，而且说起来容易做起来难，要系统地使用它们 也并不总是很简单。不过，无论如何，它们的广泛适用性令人惊讶，而且通过移去大量的显式内存分配/释放代码，它们确实增强了代码的可读性和可管理性。早在 1981年，我就指出通过大幅度减少需要显式加以管理的对象数量，使用C++&ldquo;将事情做对&rdquo;将不再是一件极其费神的艰巨任务。 </font> </p>
<p><font size="2" face="Verdana">如果你的应用领域没有能在内存管理方面助你一臂之力的类库，那么如果你还想让你的软件开发变得既快捷又能轻松得到正确结果，最好是先建立这样一个库。  </font> </p>
<p><font size="2" face="Verdana">如果你无法让内存分配和释放成为对象的&ldquo;自然行为&rdquo;，那么至少你可以通过使 用资源句柄来尽量避免内存泄漏。这里是一个示例：假设你需要从函数返回一个对象，这个对象是在自由内存堆上分配的；你可能会忘记释放那个对象&mdash;&mdash;毕竟我们 无法通过检查指针来确定其指向的对象是否需要被释放，我们也无法得知谁应该负责释放它。那么，就用资源句柄吧。比如，标准库中的auto_ptr就可以帮 助澄清：&ldquo;释放对象&rdquo;责任究竟在谁。我们来看：</font></p>
<pre><font color="#000080"><font size="2" face="Verdana">	#include<strong>&lt;</strong>memory<strong>&gt;</strong><br />	#include<strong>&lt;</strong>iostream<strong>&gt;</strong><br />	using namespace std;<br /><br />	struct S {<br />		S() { cout <strong>&lt;&lt;</strong> &quot;make an S\n&quot;; }<br />		~S() { cout <strong>&lt;&lt;</strong> &quot;destroy an S\n&quot;; }<br />		S(const S&amp;) { cout <strong>&lt;&lt;</strong> &quot;copy initialize an S\n&quot;; }<br />		S&amp; operator=(const S&amp;) { cout <strong>&lt;&lt;</strong> &quot;copy assign an S\n&quot;; }<br />	};<br /><br />	S* f()<br />	{<br />		</font><font face="Verdana"><font size="2"><strong>return new S;	// who is responsible for deleting this S?<br /></strong>	};<br /><br />	auto_ptr<strong>&lt;</strong>S<strong>&gt;</strong> g()<br />	{<br />		</font></font><font face="Verdana"><font size="2"><strong>return auto_ptr&lt; S &gt;(new S);	// explicitly transfer responsibility for deleting this S<br /></strong>	}<br /><br />	int main()<br />	{<br />		cout <strong>&lt;&lt;</strong> &quot;start main\n&quot;;<br />		S* p = f();<br />		cout <strong>&lt;&lt;</strong> &quot;after f() before g()\n&quot;;<br />	//	S* q = g();	// caught by compiler<br />		</font></font><font face="Verdana"><font size="2"><strong>auto_ptr&lt; S &gt; q = g();<br /></strong>		cout <strong>&lt;&lt;</strong> &quot;exit main\n&quot;;<br />		<strong>// leaks *p</strong><br />		<strong>// implicitly deletes *q</strong><br />	}<br /></font></font></font></pre>
<p><font size="2" face="Verdana">这里只是内存资源管理的例子；至于其它类型的资源管理，可以如法炮制。 </font> </p>
<p><font size="3" face="Verdana"><font size="2">如果在你的开发环境中无法系统地使用这种方法（比方说，你使用了第三方提供的古董代码，或者远古&ldquo;穴居人&rdquo;参与了你的项目开发），那么你在开发过程中可千万要记住使用内存防漏检测程序，或者干脆使用垃圾收集器（Garbage  Collector）。</font> </font></p>
<p><strong>原文地址：</strong><a href="http://www.research.att.com/%7Ebs/bs_faq2.html#memory-leaks">http://www.research.att.com/~bs/bs_faq2.html#memory-leaks</a></p>
          <br/>
          <span style="color:red;">
            <a href="http://shi5jin.javaeye.com/blog/120984#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 06 Sep 2007 10:43:39 +0800</pubDate>
        <link>http://shi5jin.javaeye.com/blog/120984</link>
        <guid>http://shi5jin.javaeye.com/blog/120984</guid>
      </item>
      <item>
        <title>您可以推荐一种编写代码的标准吗？</title>
        <author>shi5jin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shi5jin.javaeye.com">shi5jin</a>&nbsp;
          链接：<a href="http://shi5jin.javaeye.com/blog/120981" style="color:red;">http://shi5jin.javaeye.com/blog/120981</a>&nbsp;
          发表时间: 2007年09月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>&nbsp;&nbsp; C++ 代码编写标准的要点是：根据使用 C++ 的具体的环境和具体目的制定一套规则。因此，没有哪一种代码编写标准是符合所有需要和所有用户的。对于一个特定的应用程序（或者公司、应用领域，等等）来 说，一种好的代码编写标准当然比没有标准要好得多。话说回来，我看到过很多例子表明一种差劲的代码编写标准比没有标准还要更糟糕。 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;选择规则时，请切记细心，而且你必须对该应用领域有过硬的知识。一些最差劲的代码编写标准（&ldquo;为了保护罪犯&rdquo;，我不会提及这些 名字）的作者既没有过硬的 C++ 知识，而且对其应用领域也相对无知（他们是&ldquo;专家&rdquo;，而非开发人员），更误以为约束总是多比少好。针对前面这种误解的一个反例是：某些特性的存在会导致程 序员不得不使用甚至更糟糕的特性。怎么都好，请牢记，安全性、生产率等是设计和开发过程的所有部分的总和&mdash;&mdash;而非各种语言特性的总和，更不是所有语言的总 和。 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;基于以上原因，我的推荐有三：  </p>
<p> </p>
<ul>
    <li>看 Sutter 和 Alexandrescu 合著的《C++ 代码编写标准（C++ Coding Standards）》。Addison-Wesley 出版，ISBN 0-321-11358-。这本书里有很多好的规则，但请把这些规则看作一套元规则（meta-rules）。更明确地说，就是把这本书当作一本关于&ldquo;一 套优秀的代码编写规则应该是怎么样的&rdquo;的指南。如果你正在写代码编写标准，不看这本书将是一大损失。 </li>
    <li>看 <a href="http://www.research.att.com/%7Ebs/JSF-AV-rules.pdf"><strong>JSF 航空器 C++ 代码编写标准</strong></a>。 我认为这是一套关于编写对安全性和性能要求苛刻的代码的优秀规则。如果你从事嵌入式系统编程，那你应该考虑看一下这份标准。告诫：我参与了这些规则的制 定，所以你可以认为我带有偏心。话说回来，请将你对这份标准的建设性意见发给我。这些意见可能会推动这份标准的改进&mdash;&mdash;所有优秀的标准都会定期地被重新审 视，并且根据经验和工作环境的变化而更新。如果你不是在构建苛刻的实时系统或者对安全性要求苛刻的系统，那你会觉得这些规则过于严格&mdash;&mdash;毕竟这些规则并非 为你而设（至少并非所有这些规则都是为你而设的）。 </li>
    <li>不要使用 C 语言代码编写标准（即使已将其修改为 C++ 版），也不要使用 10 年前的 C++ 代码编写标准（即使在那时来说是很优秀的标准）。C++ 并非（仅仅）是 C，而标准 C++ 也并非（仅仅）是标准前的 C++。 </li>
</ul>
<strong>原文地址</strong>：http://www.research.att.com/~bs/bs_faq2.html#coding-standard
          <br/>
          <span style="color:red;">
            <a href="http://shi5jin.javaeye.com/blog/120981#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 06 Sep 2007 10:36:03 +0800</pubDate>
        <link>http://shi5jin.javaeye.com/blog/120981</link>
        <guid>http://shi5jin.javaeye.com/blog/120981</guid>
      </item>
      <item>
        <title>为什么编译要花这么长的时间？</title>
        <author>shi5jin</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://shi5jin.javaeye.com">shi5jin</a>&nbsp;
          链接：<a href="http://shi5jin.javaeye.com/blog/120703" style="color:red;">http://shi5jin.javaeye.com/blog/120703</a>&nbsp;
          发表时间: 2007年09月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p class="MsoNormal"><span style="font-size: 9pt; font-family: 宋体;">&nbsp;&nbsp;&nbsp; 你的编译器可能有问题。也许它太老了，也许你安装它的时候出了错，也许你用的计算机已经是个古董。在诸如此类的问题上，我无法帮助你。</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: 宋体;">&nbsp;&nbsp;&nbsp; 但是，这也是很可能的：你要编译的程序设计得非常糟糕，以至于编译器不得不检查数以百计的头文件和数万行代码。理论上来说，这是可以避免的。如果这是你购 买的库的设计问题，你对它无计可施（除了换一个更好的库），但你可以将你自己的代码组织得更好一些，以求得将修改代码后的重新编译工作降到最少。这样的设 计会更好，更有可维护性，因为它们展示了更好的概念上的分离。</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: 宋体;">&nbsp;&nbsp;&nbsp; 看看这个典型的面向对象的程序例子：</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Shape {<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; public:&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 9pt; font-family: 宋体;">使用</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">Shapes</span><span style="font-size: 9pt; font-family: 宋体;">的用户的接口<br />
&nbsp;&nbsp;&nbsp;&nbsp; </span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual void draw() const;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual void rotate(int degrees);<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; protected:&nbsp; // common data (for implementers of Shapes)<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point center;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Color col;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; };</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; class Circle : public Shape {<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public:&nbsp;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void draw() const;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void rotate(int) { }<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; protected:<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int radius;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; };</span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; class Triangle : public Shape {<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public:&nbsp;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void draw() const;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void rotate(int);<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; protected:<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point a, b, c;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; };</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: 宋体;">&nbsp;&nbsp;&nbsp; 设计思想是，用户通过</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">Shape</span><span style="font-size: 9pt; font-family: 宋体;">的</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">public</span><span style="font-size: 9pt; font-family: 宋体;">接口来操纵它们，而派生类（例如</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">Circle</span><span style="font-size: 9pt; font-family: 宋体;">和</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">Triangle</span><span style="font-size: 9pt; font-family: 宋体;">）的实现部分则共享由</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">protected</span><span style="font-size: 9pt; font-family: 宋体;">成员表现的那部分实现（</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">implementation</span><span style="font-size: 9pt; font-family: 宋体;">）。</span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; 然而，这个简单的设计理念里却隐含着三个严重的问题：</span></p>
<ul>
    <ul>
        <li>
        <div class="MsoNormal"><span style="font-size: 9pt; font-family: 宋体;">这不是一件容易的事情：确定哪些实现部分是对所有的派生类都有用的，并将之共享出来。因此，与</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">public</span><span style="font-size: 9pt; font-family: 宋体;">接口相比，</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">protected</span><span style="font-size: 9pt; font-family: 宋体;">成员往往要做多得多的改动。举例来说，虽然理论上&ldquo;中心&rdquo;</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">(center)</span><span style="font-size: 9pt; font-family: 宋体;">对所有的图形都是一个有效的概念，但当你要维护一个三角形的&ldquo;中心&rdquo;的时候，是一件非常麻烦的事情&mdash;&mdash;对于三角形，当且仅当它确实被需要的时候，计算这个中心才是有意义的。</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span></div>
        </li>
        <li>
        <div class="MsoNormal"><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">protected</span><span style="font-size: 9pt; font-family: 宋体;">成员很可能要依赖于实现部分的细节，而</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">Shape</span><span style="font-size: 9pt; font-family: 宋体;">的用户（译注：</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">user</span><span style="font-size: 9pt; font-family: 宋体;">此处译为用户，指使用</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">Shape</span><span style="font-size: 9pt; font-family: 宋体;">类的代码，下同）却不见得必须依赖它们。举例来说，很多（大多数？）使用</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">Shape</span><span style="font-size: 9pt; font-family: 宋体;">的代码在逻辑上是与&ldquo;颜色&rdquo;无关的，但是由于</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">Shape</span><span style="font-size: 9pt; font-family: 宋体;">中&ldquo;颜色&rdquo;这个定义的存在，却可能需要一堆复杂的头文件，来结合操作系统的颜色概念。</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span></div>
        </li>
        <li>
        <div class="MsoNormal"><span style="font-size: 9pt; font-family: 宋体;">当</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">protected</span><span style="font-size: 9pt; font-family: 宋体;">部分发生了改变时，使用</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">Shape</span><span style="font-size: 9pt; font-family: 宋体;">的代码必须重新编译&mdash;&mdash;即使只有派生类的实现部分才能够访问</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">protected</span><span style="font-size: 9pt; font-family: 宋体;">成员。</span></div>
        </li>
    </ul>
</ul>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; </span><span style="font-size: 9pt; font-family: 宋体;">于是，基类中的&ldquo;实现相关的信息&rdquo;</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">(information helpful to implementers)</span><span style="font-size: 9pt; font-family: 宋体;">对用户来说变成了象接口一样敏感的东西，它的存在导致了实现部分的不稳定，用户代码的无谓的重编译（当实现部分发生改变时），以及将头文件无节制地包含进用户代码中（因为&ldquo;实现相关的信息&rdquo;需要它们）。有时这被称为&ldquo;脆弱的基类问题&rdquo;</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">(brittle base class problem)</span><span style="font-size: 9pt; font-family: 宋体;">。</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: 宋体;">&nbsp;&nbsp;&nbsp; 一个很明显的解决方案就是，忽略基类中那些象接口一样被使用的&ldquo;实现相关的信息&rdquo;。换句话说，使用接口，纯粹的接口。也就是说，用抽象基类的方式来表示接口：</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Shape {<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public:&nbsp;&nbsp;&nbsp;&nbsp; //</span><span style="font-size: 9pt; font-family: 宋体;">使用</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">Shapes</span><span style="font-size: 9pt; font-family: 宋体;">的用户的接口<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; virtual void draw() const = 0;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual void rotate(int degrees) = 0;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual Point center() const = 0;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // ...<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span style="font-size: 9pt; font-family: 宋体;">没有数据<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; };</span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Circle : public Shape {<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public:&nbsp;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void draw() const;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void rotate(int) { }<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point center() const { return center; }<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // ...<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; protected:<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Point cent;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Color col;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int radius;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; };</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Triangle : public Shape {<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public:&nbsp;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void draw() const;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void rotate(int);<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point center() const;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // ...<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; protected:<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Color col;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point a, b, c;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };&nbsp;&nbsp;</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: 宋体;">&nbsp;&nbsp;&nbsp; 现在，用户代码与派生类的实现部分的变化之间的关系被隔离了。我曾经见过这种技术使得编译的时间减少了几个数量级。</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: 宋体;">&nbsp;&nbsp;&nbsp; 但是，如果确实存在着对所有派生类（或仅仅对某些派生类）都有用的公共信息时怎么办呢？可以简单把这些信息封装成类，然后从它派生出实现部分的类：</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; class Shape {<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; public:&nbsp;&nbsp;&nbsp;&nbsp; //</span><span style="font-size: 9pt; font-family: 宋体;">使用</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">Shapes</span><span style="font-size: 9pt; font-family: 宋体;">的用户的接口<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual void draw() const = 0;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual void rotate(int degrees) = 0;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual Point center() const = 0;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // no data<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; };</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; struct Common {<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Color col;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; };</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; class Circle : public Shape, protected Common {<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; public:&nbsp;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void draw() const;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void rotate(int) { }<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point center() const { return center; }<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; protected:<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point cent;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int radius;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; };</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;</span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; class Triangle : public Shape, protected Common {<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; public:&nbsp;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void draw() const;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void rotate(int);<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point center() const;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; protected:<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point a, b, c;<br />
</span><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';">&nbsp;&nbsp;&nbsp; };&nbsp; </span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 9pt; font-family: 'Courier New';"><strong>原文地址：</strong><a href="http://www.research.att.com/%7Ebs/bs_faq2.html#abstract-class">http://www.research.att.com/~bs/bs_faq2.html#abstract-class</a></span></p>
          <br/>
          <s