﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-My Love  cpp-文章分类-More  Effective  C++  </title><link>http://www.cppblog.com/lovecpp666/category/18954.html</link><description>本博客所有文章纯属学习笔记，所有随笔纯属工作感想，供己学习工作之需。当供参考，更需指正。</description><language>zh-cn</language><lastBuildDate>Fri, 30 Mar 2012 21:20:23 GMT</lastBuildDate><pubDate>Fri, 30 Mar 2012 21:20:23 GMT</pubDate><ttl>60</ttl><item><title>智能指针</title><link>http://www.cppblog.com/lovecpp666/articles/169530.html</link><dc:creator>云卷云舒</dc:creator><author>云卷云舒</author><pubDate>Fri, 30 Mar 2012 07:17:00 GMT</pubDate><guid>http://www.cppblog.com/lovecpp666/articles/169530.html</guid><wfw:comment>http://www.cppblog.com/lovecpp666/comments/169530.html</wfw:comment><comments>http://www.cppblog.com/lovecpp666/articles/169530.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lovecpp666/comments/commentRss/169530.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lovecpp666/services/trackbacks/169530.html</trackback:ping><description><![CDATA[<div><p style="margin-bottom: 0pt; margin-top: 0pt;"><strong><span style="font-size: 12pt;"></span></strong><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';"></span><span style="color: #ff0000; font-size: 12pt; font-family: 'Verdana';">&lt;1&gt;智能指针</span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 智能指针是存储指向动态分配</span><span style="color: #5e5e5e; font-size: 12pt; font-family: '宋体';">(堆)</span><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">对象指针的类</span><span style="color: #5e5e5e; font-size: 12pt; font-family: '宋体';">。</span><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">用于生存期控制,&nbsp;能够确保自动正确的销毁动态分配的对象，防止内存泄露。它的一种通用实现技术是使用引用计数(reference&nbsp;count)。智能指针类将一个计数器与类指向的对象相关联，引用计数跟踪该类有多少个对象共享同一指针。</span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">每次创建类的新对象时，初始化指针并将引用计数置为1；</span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">当对象作为另一对象的副本而创建时，拷贝构造函数拷贝指针并增加与之相应的引用计数；</span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">对一个对象进行赋值时，赋值操作符减少左操作数所指对象的引用计数（如果引用计数为减至0，则删除对象），并增加右操作数所指对象的引用计数；</span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">调用析构函数时，构造函数减少引用计数（如果引用计数减至0，则删除基础对象）。</span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';"><br /></span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #ff99cc; font-size: 12pt; font-family: 'Verdana';">备注：关于智能指针的一系列概念很模糊，很杂，在此，特意按照自己的理解整理如上。</span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><br /><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';"></span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #ff0000; font-size: 12pt; font-family: 'Verdana';">&lt;2&gt;为什么我们需要智能指针？？</span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';"></span></p><div><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当生成一个C++</span><a href="http://www.bc-cn.net/Article/kfyy/cjj/Index.html"><span style="mso-spacerun:'yes'; color:#8d8c8c; text-decoration:none ;font-size:16.0000pt; font-family:'Verdana'; "></span></a><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">object的时候如果这个class很大，这个object会占用很多空间。那么每生成一个就占用一片空间，这样会占用很多系统资源。同时降低效率。一个解决方法就是对用拷贝构造</span><span style="color: #5e5e5e; font-size: 12pt; font-family: '宋体';">函数新</span><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">生成的object，让它不存储数据，而只存储一个指向原来object数据的</span><span style="color: #5e5e5e; font-size: 12pt; font-family: '宋体';">指针</span><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';"></span><span style="color: #5e5e5e; font-size: 12pt; font-family: '宋体';">(其实就是我们所说的浅拷贝)。</span><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';"> 这样空间就节省了很多。但问题在于，这样的话两个object完全联结在了一起。如果修改了其中一个，另一个也跟着变了。所以这种方法不可取。</span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';"><br /></span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">&nbsp;&nbsp;&nbsp;&nbsp; 下面讲的技术就是解决这类问题的方法。当通过一个已有object去通过拷贝构造新object时，新object只有一个指向已有object的</span><span style="color: #5e5e5e; font-size: 12pt; font-family: '宋体';">指针</span><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">。这两个object共享数据。直到其中一个需要修改数据的时候，再把这两块数据分离。</span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';"><br /></span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这里举一个最简化的例子:假设一个class叫&nbsp;CLargeObject，里面存有很多数据。我们用一个inner&nbsp;class来把所有数据放在一起，叫CData。CData里面存有大量数据，例如一个</span><span style="color: #5e5e5e; font-size: 12pt; font-family: '宋体';">数据库</span><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">。这里用最简单的模型来表示，假设只有一个整数int&nbsp; m_nVal;&nbsp;CData里面需要包含另一个变量，叫作索引数目(reference&nbsp;count)。它记录了总共有多少CLargeObject的object正在引用着当前的CData&nbsp;</span>&nbsp;<span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">object。</span><span style="color: #5e5e5e; font-size: 16pt; font-family: 'Verdana';"></span></p><p style="margin-bottom:0pt; margin-top:0pt; "><span style="mso-spacerun:'yes'; color:#5e5e5e; font-size:16.0000pt; font-family:'Verdana'; "><br /></span></p></div><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #ff0000; font-size: 12pt; font-family: 'Verdana';">&lt;3&gt;程序代码如下：</span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #000000; ">#include</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">iostream</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;std;<br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;&nbsp;CLargeObject<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;CLargeObject(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;nVal);<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;CLargeObject(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;CLargeObject&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;ob);<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">~</span><span style="color: #000000; ">CLargeObject();<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;CLargeObject&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">operator</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;CLargeObject&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">ob);<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;SetVal(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;nNewVal);<br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;GetVal()</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">struct</span><span style="color: #000000; ">&nbsp;Data<br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Data(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;nVal):m_nVal(nVal),m_nReferenceCount(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)<br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{}<br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;friend&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;CLargeObject;<br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Data&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">get_own_copy()<br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">22</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(m_nReferenceCount&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)<br /></span><span style="color: #008080; ">23</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">24</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_nReferenceCount</span><span style="color: #000000; ">--</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">25</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;&nbsp;Data(m_nVal);<br /></span><span style="color: #008080; ">26</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">27</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;m_nReferenceCount;<br /></span><span style="color: #008080; ">28</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;m_nVal;<br /></span><span style="color: #008080; ">29</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;};<br /></span><span style="color: #008080; ">30</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Data&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">m_pData;<br /></span><span style="color: #008080; ">31</span>&nbsp;<span style="color: #000000; ">};<br /></span><span style="color: #008080; ">32</span>&nbsp;<span style="color: #000000; ">CLargeObject::CLargeObject(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;nVal)<br /></span><span style="color: #008080; ">33</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">34</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;m_pData&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Data(nVal);<br /></span><span style="color: #008080; ">35</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">36</span>&nbsp;<span style="color: #000000; ">CLargeObject::CLargeObject(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;CLargeObject&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">ob)<br /></span><span style="color: #008080; ">37</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">38</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;ob.m_pData</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">m_nReferenceCount</span><span style="color: #000000; ">++</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">39</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;m_pData&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;ob.m_pData;<br /></span><span style="color: #008080; ">40</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">41</span>&nbsp;<span style="color: #000000; ">CLargeObject::</span><span style="color: #000000; ">~</span><span style="color: #000000; ">CLargeObject()<br /></span><span style="color: #008080; ">42</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">43</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(</span><span style="color: #000000; ">--</span><span style="color: #000000; ">m_pData</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">m_nReferenceCount</span><span style="color: #000000; ">==</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)<br /></span><span style="color: #008080; ">44</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;m_pData;<br /></span><span style="color: #008080; ">45</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">46</span>&nbsp;<span style="color: #000000; ">CLargeObject&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;CLargeObject::</span><span style="color: #0000FF; ">operator</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;CLargeObject&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">ob)<br /></span><span style="color: #008080; ">47</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">48</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;ob.m_pData</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">m_nReferenceCount</span><span style="color: #000000; ">++</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">49</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(</span><span style="color: #000000; ">--</span><span style="color: #000000; ">m_pData</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">m_nReferenceCount</span><span style="color: #000000; ">==</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)<br /></span><span style="color: #008080; ">50</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;m_pData;<br /></span><span style="color: #008080; ">51</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;m_pData&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;ob.m_pData;<br /></span><span style="color: #008080; ">52</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">53</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">54</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;&nbsp;CLargeObject::SetVal(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;nNewVal)<br /></span><span style="color: #008080; ">55</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">56</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;m_pData&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;m_pData</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">get_own_copy();<br /></span><span style="color: #008080; ">57</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;m_pData</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">m_nVal&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;nNewVal;<br /></span><span style="color: #008080; ">58</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">59</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;CLargeObject::GetVal()&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">60</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">61</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;m_pData</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">m_nVal;<br /></span><span style="color: #008080; ">62</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">63</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;&nbsp;main()<br /></span><span style="color: #008080; ">64</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">65</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;CLargeObject&nbsp;obj1(</span><span style="color: #000000; ">10</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">66</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;CLargeObject&nbsp;obj2(obj1);<br /></span><span style="color: #008080; ">67</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;obj2.SetVal(</span><span style="color: #000000; ">22</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">68</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">obj1.GetVal()</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">10</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">69</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">obj2.GetVal()</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">22</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">70</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">}</span></div><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';"><br /></span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #ff0000; font-size: 12pt; font-family: 'Verdana';">&lt;4&gt;代码解析：</span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">32~35行：</span><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">构造函数,建立堆上的对象</span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">36~40行：拷贝构造函数，仅仅引用计数加1，通过赋值语句完成数据共享</span></p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">46~53行：赋值函数&nbsp; </span><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';"><br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; "></span> <span style="color: #000000; ">CLargeObject&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;CLargeObject::</span><span style="color: #0000FF; ">operator</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;CLargeObject&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">ob)<br /></span><span style="color: #008080; "></span><span style="color: #000000; ">{<br /></span><span style="color: #008080; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp; ob.m_pData</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">m_nReferenceCount</span><span style="color: #000000; ">++</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(</span><span style="color: #000000; ">--</span><span style="color: #000000; ">m_pData</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">m_nReferenceCount</span><span style="color: #000000; ">==</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)<br /></span><span style="color: #008080; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete&nbsp;m_pData;</span><span style="color: #008080; "><br /></span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp; m_pData&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;ob.m_pData;<br /></span><span style="color: #008080; ">&nbsp;</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">;</span><span style="color: #008080; "><br /></span>&nbsp;<span style="color: #000000; ">}</span></div><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';"></span></p><div><span style="font-size: 12pt; color: #ff99cc;"><br />注意理解：</span><br /><span style="font-size: 12pt; color: #ff99cc;">1&gt;为了防止自身赋值(即就是如果两个对象相同)，</span><br /><span style="font-size: 12pt; color: #ff99cc;">&nbsp;&nbsp;&nbsp; 在对左对象(或者左操作数)的使用计数操作之前使原对象的使用计数先加1</span><br /><span style="font-size: 12pt; color: #ff99cc;">&nbsp;&nbsp;&nbsp; 若恰相等，if语句必进行减1操作，意味着计数前后没有改变，达到目的</span><br /><span style="font-size: 12pt; color: #ff99cc;">&nbsp;&nbsp;&nbsp; 若不相等，意味着原对象计数加1，被赋值对象计数减1，也成立</span><br /><span style="font-size: 12pt; color: #ff99cc;">&nbsp;&nbsp;&nbsp; 然后相应成员进行赋值</span><br /><span style="font-size: 12pt; color: #ff99cc;">2&gt;如果左对象的使用计数减至0，那么赋值操作符必须删除它之前所指向的对象，</span><br /><span style="font-size: 12pt; color: #ff99cc;">&nbsp;&nbsp;&nbsp; 再进行相应成员赋值</span><br /><br /><span style="font-size: 12pt;">41~45行：析构函数，通过计数判断是否为最后一次删除。若是，摧毁共享数据；若非，仅仅计数减1.达到目的</span><br /><br /><span style="font-size: 12pt;">54~58行：设置值函数，可以看出其中调用了函数get_own_copy()</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">1</span>&nbsp;<span style="color: #000000; ">Data&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">get_own_copy()<br /></span><span style="color: #008080; ">2</span> <span style="color: #000000; ">{<br /></span><span style="color: #008080; ">3</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(m_nReferenceCount&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)<br /></span><span style="color: #008080; ">4</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">5</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp; m_nReferenceCount</span><span style="color: #000000; ">--</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">6</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;&nbsp;Data(m_nVal);<br /></span><span style="color: #008080; ">7</span> <span style="color: #000000; ">}</span></div><div><span style="color: #000000; font-size: 12pt;">56行：m_pData&nbsp;</span><span style="color: #000000; font-size: 12pt;">=</span><span style="color: #000000; font-size: 12pt;">&nbsp;m_pData</span><span style="color: #000000; font-size: 12pt;">-&gt;</span><span style="color: #000000; font-size: 12pt;">get_own_copy();<br /></span><span style="color: #ff99cc; font-size: 12pt;">左操作数的指针成员(m_pData)很关键。<br /></span><span style="color: #ff99cc; font-size: 12pt;">若引用计数为1，说明该共享数据仅仅被引用了一次，那么，修改值就仅仅需要在原内存中进行更改，所以，返回this指针，即本身指针<br /></span><span style="color: #ff99cc; font-size: 12pt;">若引用计数大于1，说明该共享数据不仅被一个对象引用。</span><span style="color: #ff99cc; font-size: 12pt;">那么，修改该值的就要统筹兼顾，顾全大局，步骤如下：<br /></span><span style="color: #ff99cc; font-size: 12pt;">首先：保证原数据块依然存在<br /></span><span style="color: #ff99cc; font-size: 12pt;">另外：使引用计数减1<br /></span><span style="color: #ff99cc; font-size: 12pt;">最后：建立一个新的数据块<br /></span><span style="color: #ff99cc; font-size: 12pt;">函数结束，返回新数据块的指针赋值给m_pData&nbsp; <br /></span><span style="color: #ff99cc; font-size: 12pt;">即就是实现了所谓的分离</span><span style="color: #000000; font-size: 12pt;"><br /></span><span style="color: #000000; font-size: 12pt;">57行：m_pData-&gt;m_nVal = nNewVal;<br /></span><span style="color: #000000; font-size: 12pt;">通过指针实现新数据的输入。</span><span style="color: #000000; font-size: 12pt;"><br /><br /></span><span style="color: #000000; font-size: 12pt;">59~62行：取值函数。之所以定义为常函数是因为防止在函数内部m_pData被修改。</span></div></div><p>&nbsp;</p><p style="margin-bottom: 0pt; margin-top: 0pt;"><span style="color: #5e5e5e; font-size: 12pt; font-family: 'Verdana';">&lt;5&gt;自己实现的部分代码：<br /></span></p></div><img src ="http://www.cppblog.com/lovecpp666/aggbug/169530.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lovecpp666/" target="_blank">云卷云舒</a> 2012-03-30 15:17 <a href="http://www.cppblog.com/lovecpp666/articles/169530.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>只允许对象产生于堆内</title><link>http://www.cppblog.com/lovecpp666/articles/169442.html</link><dc:creator>云卷云舒</dc:creator><author>云卷云舒</author><pubDate>Thu, 29 Mar 2012 08:53:00 GMT</pubDate><guid>http://www.cppblog.com/lovecpp666/articles/169442.html</guid><wfw:comment>http://www.cppblog.com/lovecpp666/comments/169442.html</wfw:comment><comments>http://www.cppblog.com/lovecpp666/articles/169442.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lovecpp666/comments/commentRss/169442.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lovecpp666/services/trackbacks/169442.html</trackback:ping><description><![CDATA[<div><span style="font-size: 12pt;">&nbsp;&nbsp; 只允许对象生成于堆内？怎么理解？假如手头上有一个类Person，当你在程序中写下Person rn时，编译器悄悄地做了两件事：调用constructor构造对象rn，在弹栈时，调用destructor析构对象rn。对象rn的构造和析构全部由编译器负责，这是栈的特性！诸所周知，对象rn生成于栈内。我们的要求是什么？&#8220;只允许对象生成于堆内。&#8221;rn明显违背了我们的要求，它应该被禁止。<br />&nbsp;&nbsp; 这种 &#8220;坑爹型&#8221;的事情很好办，只要让Person的构造函数或者析构函数成为private就OK了。也许许多人会有这样的想法，也好，咱再往下进一步思考，如果那样的话，这个类可以实现继承吗？另外，这个类允许其他类拥有它的对象吗？No，即就是禁止包含。<br />&nbsp;&nbsp; 答案是否定的。<br />&nbsp;&nbsp; 那怎么办呢？<div>&nbsp;&nbsp; 解决的方法也很简单，解除继承的副作用只需让Person的析构函数成为protected就可以了；解决内含的副作用只需让Test中的成员变量ps成为Person*类型并在Test的构造/析构函数中对成员变量做初始化和释放操作就可以了。本例完整的代码如下所示。<br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Person<br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Person()<br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Con()</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Person(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;x)<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a</span><span style="color: #000000; ">=</span><span style="color: #000000; ">x;<br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Con(x)</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;<br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;&nbsp;Destroy()<br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">protected</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">~</span><span style="color: #000000; ">Person()<br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Des</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;<br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">22</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">23</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;a;<br /></span><span style="color: #008080; ">24</span>&nbsp;<span style="color: #000000; ">};<br /></span><span style="color: #008080; ">25</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;&nbsp;Student:</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;Person<br /></span><span style="color: #008080; ">26</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">27</span>&nbsp;<span style="color: #000000; ">};<br /></span><span style="color: #008080; ">28</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Test<br /></span><span style="color: #008080; ">29</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">30</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">31</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Test()<br /></span><span style="color: #008080; ">32</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">33</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #ff0000;">ps</span><span style="color: #ff0000;">=</span><span style="color: #ff0000;">new</span><span style="color: #ff0000;">&nbsp;&nbsp;Person();&nbsp;&nbsp;&nbsp; //堆上对象</span><span style="color: #000000;"><br /></span><span style="color: #008080; ">34</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">35</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">~</span><span style="color: #000000; ">Test()<br /></span><span style="color: #008080; ">36</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">37</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ps</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Destroy();<br /></span><span style="color: #008080; ">38</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">39</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">40</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Person&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">ps;<br /></span><span style="color: #008080; ">41</span>&nbsp;<span style="color: #000000; ">};<br /></span><span style="color: #008080; ">42</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;main()<br /></span><span style="color: #008080; ">43</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">44</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;Test&nbsp;t1;<br /></span><span style="color: #008080; ">45</span>&nbsp;<span style="color: #000000; ">}</span></div><br />这样子的类Person,可以实现继承的功能。也可以创建堆上的对象。Do&nbsp; you&nbsp; konw?&nbsp; 我有点懵啦......</div></span></div><img src ="http://www.cppblog.com/lovecpp666/aggbug/169442.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lovecpp666/" target="_blank">云卷云舒</a> 2012-03-29 16:53 <a href="http://www.cppblog.com/lovecpp666/articles/169442.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>7.2 限制某个类所能产生的对象数量 </title><link>http://www.cppblog.com/lovecpp666/articles/169428.html</link><dc:creator>云卷云舒</dc:creator><author>云卷云舒</author><pubDate>Thu, 29 Mar 2012 07:56:00 GMT</pubDate><guid>http://www.cppblog.com/lovecpp666/articles/169428.html</guid><wfw:comment>http://www.cppblog.com/lovecpp666/comments/169428.html</wfw:comment><comments>http://www.cppblog.com/lovecpp666/articles/169428.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lovecpp666/comments/commentRss/169428.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lovecpp666/services/trackbacks/169428.html</trackback:ping><description><![CDATA[<div><span style="font-size: 12pt;">如何禁止产生类对象呢？只要将类的构造函数用private修饰即可。 </span><p><span style="font-size: 12pt;">更进一步，如何限制类只能产生一个类对象呢？只要借助于友元函数的static对象即可。书中以Printer()为例做了说明。</span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Printer&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; ">{&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Printer()&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">thePrinter&nbsp;constructed</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;what()&nbsp;&nbsp;<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">It's&nbsp;a&nbsp;printer</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;friend&nbsp;Printer&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;thePrinter();&nbsp;&nbsp;<br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">};&nbsp;&nbsp;<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">Printer&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;thePrinter()&nbsp;&nbsp;<br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; ">{&nbsp;&nbsp;<br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;Printer&nbsp;p;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;p;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; ">}&nbsp; <br /></span></div></div><div><p><span style="font-size: 12pt;">这样一来，Printer类的对象就只有唯一的p，而且只有在首次调用thePrinter函数时才生成，不调用就不生成。将类的构造函数用private修饰还有另外一个作用：禁止类被继承。任何想要继承Printer的新类都不能顺利构造出对象来。</span></p> <p><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp; 接下来就应该讨论限制类所能产生的对象数量为N(N&gt;1)的情况了。不过在正式提出解决方案之前，首先来了解一下伪构造函数。所谓伪构造函数就是类的一种static函数，它能够产生对象，作用就像构造函数。之所以需要构造函数，是因为类真正的构造函数现已被private修饰，不能被外界调 用。仍然以Printer为例，删除友元函数thePrinter，为类添加static Printer*  makePrinter()成员函数，其代码为：</span></p><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Printer&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; ">{&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Printer()&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">thePrinter&nbsp;constructed</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;what()&nbsp;&nbsp;<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">It's&nbsp;a&nbsp;printer</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;Printer</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;makePrinter()&nbsp;&nbsp;<br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Printer();&nbsp;&nbsp;<br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000;">};&nbsp; <br /></span></div></div><div><p><span style="font-size: 12pt;">如此定义的Printer类就没有生成对象数量上的限制了，但是它不允许被继承。makePrinter函数就是Printer类的伪构造函数。</span></p> <p><span style="font-size: 12pt;">认识了伪构造函数之后再回到之前的问题：如何限制类所能产生的对象数量为N(N&gt;1)？书中提出的方案是以上述伪构造函数为基础的，只要为Printer类添加一个计数就好了。</span></p></div><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Printer&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; ">{&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Printer()&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">thePrinter&nbsp;constructed</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;counter;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:&nbsp;&nbsp;<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;TooManyObject&nbsp;&nbsp;<br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:&nbsp;&nbsp;<br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;what()&nbsp;&nbsp;<br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Too&nbsp;many&nbsp;Object</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;&nbsp;<br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;what()&nbsp;&nbsp;<br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">It's&nbsp;a&nbsp;printer</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br /></span><span style="color: #008080; ">22</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;Printer</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;makePrinter()&nbsp;&nbsp;<br /></span><span style="color: #008080; ">23</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<br /></span><span style="color: #008080; ">24</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(</span><span style="color: #000000; ">++</span><span style="color: #000000; ">counter</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">10</span><span style="color: #000000; ">)&nbsp;&nbsp;<br /></span><span style="color: #008080; ">25</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<br /></span><span style="color: #008080; ">26</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Stop&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;<br /></span><span style="color: #008080; ">27</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">28</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br /></span><span style="color: #008080; ">29</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Printer();&nbsp;&nbsp;<br /></span><span style="color: #008080; ">30</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br /></span><span style="color: #008080; ">31</span>&nbsp;<span style="color: #000000; ">};&nbsp;&nbsp;<br /></span><span style="color: #008080; ">32</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;Printer::counter</span><span style="color: #000000; ">=</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp; <br /></span></div><div><span style="font-size: 12pt;"><br />上面代码实现出的Printer类被限制只能最多产生10个对象</span></div><img src ="http://www.cppblog.com/lovecpp666/aggbug/169428.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lovecpp666/" target="_blank">云卷云舒</a> 2012-03-29 15:56 <a href="http://www.cppblog.com/lovecpp666/articles/169428.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[20.2] C++ 怎样同时实现动态绑定和静态类型？</title><link>http://www.cppblog.com/lovecpp666/articles/169422.html</link><dc:creator>云卷云舒</dc:creator><author>云卷云舒</author><pubDate>Thu, 29 Mar 2012 07:21:00 GMT</pubDate><guid>http://www.cppblog.com/lovecpp666/articles/169422.html</guid><wfw:comment>http://www.cppblog.com/lovecpp666/comments/169422.html</wfw:comment><comments>http://www.cppblog.com/lovecpp666/articles/169422.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lovecpp666/comments/commentRss/169422.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lovecpp666/services/trackbacks/169422.html</trackback:ping><description><![CDATA[<div><p><span style="font-size: 12pt;">当你有一个对象的指针，而对象实际是该指针类型的派生类（例如：一个 Vehicle*指针实际指向一个Car 对象）。</span></p><p><span style="font-size: 12pt;">由此有两种类型：指针的（静态）类型（在此是Verhicle），和指向的对象的（动态）类型（在此是Car）。</span><br /></p><p><span style="color: #ff0000; font-size: 12pt;">&lt;1&gt;静态类型 </span><br /></p><p><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp; 意味着成员函数调用的合法性被尽可能早地检查：编译器在编译时。编译器用指针的静态类型决定成员函数调用是否合法。如果指针类型能够处理成员函数，那么指针 所指对象当然能很好的处理它。例如，如果&nbsp;Vehicle&nbsp;有某个成员函数，则由于Car是一种Vehicle，那么Car&nbsp;当然也有该成员函数。</span></p><p><span style="font-size: 12pt; color: #ff0000;">&lt;2&gt;动态绑定</span></p><p><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 12pt;">意味着成员函数调用的代码地址在最终时刻才被决定：基于运行时的对象动态类型。因为绑定到实际被调用的代码这个过程是动态完成的（在运行时），所以被称为&#8220;动态绑定&#8221;。动态绑定是虚函数导致的结果之一。 <br /></span></p></div><img src ="http://www.cppblog.com/lovecpp666/aggbug/169422.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lovecpp666/" target="_blank">云卷云舒</a> 2012-03-29 15:21 <a href="http://www.cppblog.com/lovecpp666/articles/169422.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>7.1：虚拟构造函数[1]</title><link>http://www.cppblog.com/lovecpp666/articles/169411.html</link><dc:creator>云卷云舒</dc:creator><author>云卷云舒</author><pubDate>Thu, 29 Mar 2012 06:36:00 GMT</pubDate><guid>http://www.cppblog.com/lovecpp666/articles/169411.html</guid><wfw:comment>http://www.cppblog.com/lovecpp666/comments/169411.html</wfw:comment><comments>http://www.cppblog.com/lovecpp666/articles/169411.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lovecpp666/comments/commentRss/169411.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lovecpp666/services/trackbacks/169411.html</trackback:ping><description><![CDATA[<div><div><span style="font-size: 12pt;"></span><span style="font-size: 12pt;"><div><span style="font-size: 12pt;">参考more&nbsp; effective&nbsp; C++ 7.1：将构造函数和非成员函数虚拟化</span></div><br />在了解代码之前，请先仔细阅读这些概念：<br /><br /></span></div><div><span style="font-size: 12pt; color: #ff0000;">&lt;1&gt;什么是"虚构造函数(virtual constructor)"？</span><span style="font-size: 12pt;"><br />一种允许你做一些 C++不直接支持的事情的用法。</span><br /><span style="font-size: 12pt;"> 你可能通过虚函数 virtual clone()（对于拷贝构造函数）或虚函数 virtual create()（对于默认构造函数），得到虚构造函数产生的效果。<br /><br /><div><span style="font-size: 12pt; color: #ff0000;">&lt;2&gt;虚拟拷贝构造函数：</span><span style="font-size: 12pt;"><br />一种特殊种类的虚拟构造函数&#8213;&#8213;虚拟拷贝构造函数&#8213;&#8213;也有着广泛的</span><span style="font-size: 12pt;">用途。<br />虚拟拷贝构造函数能返回一个指针，指向调用该函数的对象的新拷贝。</span><br /><span style="font-size: 12pt;"> 因为这种行为特性，虚拟拷贝构造函数的名字一般都是copySelf，cloneSelf或者是象下面这样就叫做clone。</span><br /><span style="font-size: 12pt;"><br /><br /><div><span style="color: #ff0000;">&lt;3&gt;协变返回类型：</span><br /> <span style="font-size: 12pt;">注意:下述代码的实现利用了被采纳的较宽松的虚拟函数返回值类型规则。</span><br /><span style="font-size: 12pt;"> 被派生类重定义的虚拟函数不用必须与基类的虚拟函数具有一样的返回类型。</span><br /><span style="font-size: 12pt;"> 如果函数的返回类型是一个指向基类的指针（或一个引用），那么派生类的函数可以返回一个派生类的指针（或引用）。</span><br /><span style="font-size: 12pt;"> 这不是C++的类型检查上的漏洞，它使得有可能声明像虚拟构造函数这样的函数。</span><br /><span style="font-size: 12pt;"> 这就是为什么Circle 的clone函数能够返回Circle *和Square 的clone能够返回Square *的原因，即使Shape 的clone返回值类型为Shape *。<br /><div><span style="font-size: 12pt;"><span style="font-size: 12pt;"><span style="font-size: 12pt; color: #0000ff;">备注：根据坊间记录，以前的编译器是不支持这个东东的。</span></span></span></div></span><br /><div><span style="font-size: 12pt; color: #ff0000;">&lt;4&gt;虚构造函数</span></div><div>因为它能建立新对象，它的行为与构造函数相似，而且因为它能建立不同类型的对象，我们称它为虚拟构造函数。<br /> 虚拟构造函数是指能够根据输入给它的数据的不同而建立不同类型的对象。<br /> 虚拟构造函数在很多场合下都有用处，从磁盘（或者通过网络连接，或者从磁带机上）读取对象信息只是其中的一个应用。<br /><br />网摘代码如下：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #000000; ">#include</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">iostream</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;std;<br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Shape&nbsp;<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">virtual</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">~</span><span style="color: #000000; ">Shape()&nbsp;{&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;虚析构函数<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #008000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;virtual&nbsp;void&nbsp;draw()&nbsp;=&nbsp;0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;纯虚函数<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #008000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">virtual&nbsp;void&nbsp;move()&nbsp;=&nbsp;0;<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #008000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /><br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #008000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;使用拷贝构造函数&nbsp;,more&nbsp;effective&nbsp;c++中成为虚拟拷贝构造函数&nbsp;&nbsp;。涉及"协变返回类型"</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #008000; "></span><span style="color: #0000FF; ">virtual</span><span style="color: #000000; ">&nbsp;Shape</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;clone()&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;使用默认构造函数</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #008000; "></span><span style="color: #0000FF; ">virtual</span><span style="color: #000000; ">&nbsp;Shape</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;create()&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">};<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Circle&nbsp;:&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;Shape&nbsp;<br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;Circle()<br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Construction&nbsp;&nbsp;&nbsp;Circle</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;<br /></span><span style="color: #008080; ">22</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">23</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">24</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">在&nbsp;clone()&nbsp;成员函数中，代码&nbsp;new&nbsp;Circle(*this)&nbsp;调用&nbsp;Circle&nbsp;的拷贝构造函数来复制this的状态到新创建的Circle对象</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">25</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;Circle</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;clone()&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;{&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Circle(</span><span style="color: #000000; ">*</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">);}&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">26</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">在&nbsp;create()成员函数中，代码&nbsp;new&nbsp;Circle()&nbsp;调用Circle的默认构造函数。</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">27</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;Circle</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;create()&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;{&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Circle();}&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">28</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">~</span><span style="color: #000000; ">Circle()<br /></span><span style="color: #008080; ">29</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">30</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Destroy&nbsp;&nbsp;Circle</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;<br /></span><span style="color: #008080; ">31</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">32</span>&nbsp;<span style="color: #000000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /></span><span style="color: #008000; "><br /></span><span style="color: #008080; ">33</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">};<br /></span><span style="color: #008080; ">34</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">35</span>&nbsp;<span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Square&nbsp;:&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;Shape&nbsp;<br /></span><span style="color: #008080; ">36</span>&nbsp;<span style="color: #000000; ">&nbsp;{<br /></span><span style="color: #008080; ">37</span>&nbsp;<span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">38</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Square()<br /></span><span style="color: #008080; ">39</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">40</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Construction&nbsp;&nbsp;&nbsp;Square</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;<br /></span><span style="color: #008080; ">41</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">42</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">43</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">在clone()成员函数中，代码&nbsp;new&nbsp;Square(*this)&nbsp;调用Square的拷贝构造函数来复制this的状态到新创建的Square对象</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">44</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Square</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;clone()&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;{&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Square(</span><span style="color: #000000; ">*</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">);}<br /></span><span style="color: #008080; ">45</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">在&nbsp;create()成员函数中，代码&nbsp;new&nbsp;Square()&nbsp;调用Square的默认构造函数。</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">46</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Square</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;create()&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;{&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Square();}<br /></span><span style="color: #008080; ">47</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">~</span><span style="color: #000000; ">Square()<br /></span><span style="color: #008080; ">48</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">49</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Destroy&nbsp;&nbsp;Square</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;<br /></span><span style="color: #008080; ">50</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">51</span>&nbsp;<span style="color: #000000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /></span><span style="color: #008000; "><br /></span><span style="color: #008080; ">52</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">};<br /></span><span style="color: #008080; ">53</span>&nbsp;<span style="color: #000000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">虚构造函数</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">54</span>&nbsp;<span style="color: #008000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;userCode(Shape</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;s)<br /></span><span style="color: #008080; ">55</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">56</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Shape</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;s2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;s.clone();<br /></span><span style="color: #008080; ">57</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Shape</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;s3&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;s.create();<br /></span><span style="color: #008080; ">58</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif" alt="" /></span><span style="color: #008000; "><br /></span><span style="color: #008080; ">59</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;s2;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;在此处，需要虚析构函数</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">60</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;s3;<br /></span><span style="color: #008080; ">61</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">62</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;main()&nbsp;<br /></span><span style="color: #008080; ">63</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">64</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;Circle&nbsp;c;<br /></span><span style="color: #008080; ">65</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;userCode(c);<br /></span><span style="color: #008080; ">66</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">67</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;Square&nbsp;s;<br /></span><span style="color: #008080; ">68</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;userCode(s);<br /></span><span style="color: #008080; ">69</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">70</span>&nbsp;<span style="color: #000000; "></span><span style="color: #008000; ">/*</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">71</span>&nbsp;<span style="color: #008000; ">运行结果：<br /></span><span style="color: #008080; ">72</span>&nbsp;<span style="color: #008000; ">Construction&nbsp;&nbsp;&nbsp;Circle<br /></span><span style="color: #008080; ">73</span>&nbsp;<span style="color: #008000; ">Construction&nbsp;&nbsp;&nbsp;Circle<br /></span><span style="color: #008080; ">74</span>&nbsp;<span style="color: #008000; ">Destroy&nbsp;&nbsp;Circle<br /></span><span style="color: #008080; ">75</span>&nbsp;<span style="color: #008000; ">Destroy&nbsp;&nbsp;Circle<br /></span><span style="color: #008080; ">76</span>&nbsp;<span style="color: #008000; ">Construction&nbsp;&nbsp;&nbsp;Square<br /></span><span style="color: #008080; ">77</span>&nbsp;<span style="color: #008000; ">Construction&nbsp;&nbsp;&nbsp;Square<br /></span><span style="color: #008080; ">78</span>&nbsp;<span style="color: #008000; ">Destroy&nbsp;&nbsp;Square<br /></span><span style="color: #008080; ">79</span>&nbsp;<span style="color: #008000; ">Destroy&nbsp;&nbsp;Square<br /></span><span style="color: #008080; ">80</span>&nbsp;<span style="color: #008000; ">Destroy&nbsp;&nbsp;Square<br /></span><span style="color: #008080; ">81</span>&nbsp;<span style="color: #008000; ">Destroy&nbsp;&nbsp;Circle<br /></span><span style="color: #008080; ">82</span>&nbsp;<span style="color: #008000; "></span><span style="color: #008000; ">*/</span><span style="color: #000000;"><br /></span><span style="color: #008080; "></span><span style="color: #000000; "></span></div></div></div> </span></div> </span></div></div><img src ="http://www.cppblog.com/lovecpp666/aggbug/169411.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lovecpp666/" target="_blank">云卷云舒</a> 2012-03-29 14:36 <a href="http://www.cppblog.com/lovecpp666/articles/169411.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第六章：效率</title><link>http://www.cppblog.com/lovecpp666/articles/169375.html</link><dc:creator>云卷云舒</dc:creator><author>云卷云舒</author><pubDate>Thu, 29 Mar 2012 01:49:00 GMT</pubDate><guid>http://www.cppblog.com/lovecpp666/articles/169375.html</guid><wfw:comment>http://www.cppblog.com/lovecpp666/comments/169375.html</wfw:comment><comments>http://www.cppblog.com/lovecpp666/articles/169375.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lovecpp666/comments/commentRss/169375.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lovecpp666/services/trackbacks/169375.html</trackback:ping><description><![CDATA[<div><span style="font-size: 12pt; color: #ff0000;">6.4：理解临时对象</span><br /><span style="font-size: 12pt;">&lt;1&gt;为了使函数成功调用而进行隐式类型转换和函数返回对象时</span><br /><br /><span style="font-size: 12pt;">&lt;2&gt;当传送给函数的对象类型与参数类型不匹配时会产生的一种情况</span><br /><br /><span style="font-size: 12pt;">&lt;3&gt;当通过传值方式传递对象或者传递常量引用参数时，才会发生类型转换</span><br /><span style="font-size: 12pt;">示范代码如下：</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #000000; ">#include</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">iostream</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;std;<br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;&nbsp;Test<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;a;<br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Test(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;data</span><span style="color: #000000; ">=</span><span style="color: #000000; ">10</span><span style="color: #000000; ">):a(data)<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Construction&nbsp;:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">~</span><span style="color: #000000; ">Test()<br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Destroy&nbsp;:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;<br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;Print()&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">data:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">a</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;<br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; ">};<br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;Fun1(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Test&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;a)<br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">22</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;a.Print();<br /></span><span style="color: #008080; ">23</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">24</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;Fun2(Test&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">b)<br /></span><span style="color: #008080; ">25</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">26</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;b.Print();<br /></span><span style="color: #008080; ">27</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">28</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;&nbsp;Fun3(Test&nbsp;c)<br /></span><span style="color: #008080; ">29</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">30</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;c.Print();<br /></span><span style="color: #008080; ">31</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">32</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;&nbsp;main()<br /></span><span style="color: #008080; ">33</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">34</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Fun1(</span><span style="color: #000000; ">10</span><span style="color: #000000; ">);&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">传递常量引用参数<br /></span><span style="color: #008080; ">35</span>&nbsp;<span style="color: #008000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp; Fun2(10);&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">error!!&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">非常引用</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">36</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Fun3(</span><span style="color: #000000; ">20</span><span style="color: #000000; ">);&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">传值方式传递对象</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">37</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">}<br /></span><span style="color: #008080; ">38</span>&nbsp;<span style="color: #000000; "></span><span style="color: #008000; ">/*</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">39</span>&nbsp;<span style="color: #008000; ">Construction&nbsp;:0012FE88<br /></span><span style="color: #008080; ">40</span>&nbsp;<span style="color: #008000; ">data:10<br /></span><span style="color: #008080; ">41</span>&nbsp;<span style="color: #008000; ">Destroy&nbsp;:0012FE88<br /></span><span style="color: #008080; ">42</span>&nbsp;<span style="color: #008000; ">Construction&nbsp;:0012FE6C<br /></span><span style="color: #008080; ">43</span>&nbsp;<span style="color: #008000; ">data:20<br /></span><span style="color: #008080; ">44</span>&nbsp;<span style="color: #008000; ">Destroy&nbsp;:0012FE6C<br /></span><span style="color: #008080; ">45</span>&nbsp;<span style="color: #008000; "></span><span style="color: #008000; ">*/</span></div><br /><span style="font-size: 12pt; color: #ff0000;">6.6：通过重载避免隐式类型转换</span><br /><br /><span style="font-size: 12pt; color: #ff0000;">6.9：理解虚拟函数、多继承、虚基类和RTTI所需的代价 </span><br /><br /><span style="font-size: 12pt;">&nbsp;&lt;1&gt;virtual table只实现了虚拟函数的一半机制，如果只有这些是没有用的。只</span><span style="font-size: 12pt;">有用某种方法指出每个对象对应的vtbl时，它们才能使用。这是virtual table pointer 的工作，它来建立这种联系。 </span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp; 每个声明了虚函数的对象都带有它，它是一个看不见的数据成员，指向对应类的virtual table 。这个看不见的数据成员也称为vptr，被编译器加在对象里，位置只有才编译器知道。从理论上讲，我们可以认为包含有虚函数的对象的布局是这样的：</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp; 假如我们有一个程序，包含几个C1和C2对象。对象，vptr和刚刚我们讲述的vtabl之间的关系，在程序里我们可以这样去想象：<br /><img src="http://www.cppblog.com/images/cppblog_com/lovecpp666/虚表.GIF" alt="" border="0" height="335" width="475" /><br /><br /><br />下面考虑这段代码的执行：<br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">1</span>&nbsp;<span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;makeACall(C1&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">pC1)<br /></span><span style="color: #008080; ">2</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">3</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;pC1</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">f1();<br /></span><span style="color: #008080; ">4</span>&nbsp;<span style="color: #000000; ">}</span></div><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp; </span><span style="font-size: 12pt;">通过指针 pC1调用虚拟函数f1。仅仅看这段代码，你不会知道它调用的是那一个f1 函数?? C1::f1 或C2::f1，因为pC1可以指向C1对象也可以指向C2</span><span style="font-size: 12pt;">对象。尽管如此编译器仍然得为在makeACall的f1 函数的调用生成代码，它必须确保无论 pC1指向什么对象，函数的调用必须正确。编译器生成的代码会做如下这些事情： </span><br /><br /><span style="font-size: 12pt;">(1)通过对象的 vptr 找到类的 vtbl。这是一个简单的操作，因为编译器知道在对象内哪里能找到 vptr(毕竟是由编译器放置的它们) 。因此这个代价只</span><span style="font-size: 12pt;">是一个偏移调整(以得到vptr)和一个指针的间接寻址(以得到 vtbl)。 </span><br /><br /><span style="font-size: 12pt;">(2)找到对应vtbl内的指向被调用函数的指针(在上例中是f1) 。这也是很简单的，因为编译器为每个虚函数在vtbl 内分配了一个唯一的索引。这步的代</span><span style="font-size: 12pt;">价只是在vtbl 数组内的一个偏移。 </span><br /><br /><div><span style="font-size: 12pt;">(3) 调用第二步找到的的指针所指向的函数。如果我们假设每个对象有一个隐藏的数据叫做vptr，而且f1 在 vtbl 中的索引为i，此语句 </span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp; pC1-&gt;f1(); </span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 12pt;">生成的代码就是这样的:</span><span style="font-size: 12pt;"><br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #ff0000; font-size: 12pt;">&nbsp;&nbsp; (</span><span style="color: #ff0000; font-size: 12pt;">*</span><span style="color: #ff0000; font-size: 12pt;">pC1</span><span style="color: #ff0000; font-size: 12pt;">-&gt;</span><span style="color: #ff0000; font-size: 12pt;">vptr[i])(pC1);&nbsp;&nbsp;&nbsp; //调用被vtbl中第i个单元指向的函数，而pC1-&gt;vptr指向的是vtbl;pC1被作为this指针传递给函数。</span><span style="color: #000000;"><br /></span></div><span style="font-size: 12pt;"><br />(4)实际上，虚函数不能是内联函数<br />&nbsp;&nbsp;&nbsp; </span><span style="font-size: 12pt;">因为&#8220;内联&#8221;是指&#8220;在编译期间用被调用的函数体本身来代替函数调用的</span><span style="font-size: 12pt;">指令，&#8221;但是虚函数的&#8220;虚&#8221;是指&#8220;直到运行时才能知道要调用的是哪一个函数。&#8221;如 </span><span style="font-size: 12pt;">果编译器在某个函数的调用点不知道具体是哪个函数被调用，你就能知道为什么</span><span style="font-size: 12pt;">它不会内联该函数的调用。这是虚函数所需的第三个代价：你实际上放弃了使用</span><span style="font-size: 12pt;">内联函数。（当通过对象调用虚函数时，它可以被内联，但是大多数虚函数是通</span><span style="font-size: 12pt;">过对象的指针或引用被调用的，这种调用不能被内联。因为这种调用是标准的调</span><span style="font-size: 12pt;">用方式，所以虚函数实际上不能被内联。）<br /><br />&lt;2&gt;虚基类<br /></span><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp; 多继承经常导致对虚基类的需求。没有虚基类，如果一个派生类有一个以上从基类的继承路径，基类的数据成员被复制到每一个继承类对象里，继承类与基</span><span style="font-size: 12pt;">类间的每条路径都有一个拷贝。程序员一般不会希望发生这种复制，而把基类定义为虚基类则可以消除这种复制。</span><span style="font-size: 12pt;"><br />下面考虑这幅图：所谓的菱形继承<br /><img src="http://www.cppblog.com/images/cppblog_com/lovecpp666/菱形继承.GIF" alt="" border="0" height="134" width="371" /><br /><br />这也就是虚基类产生的原因。<br /><br />&lt;3&gt;运行时类型识别<br /><div>&nbsp;&nbsp;&nbsp; RTTI 能让我们在运行时找到对象和类的有关信息，所以肯定有某个地方存储了这些信息让我们查询。这些信息被存储在类型为 type_info 的对象里，你能通过使用typeid操作符访问一个类的type_info 对象。 <br /><div>&nbsp;&nbsp;&nbsp; 在每个类中仅仅需要一个RTTI的拷贝，但是必须有办法得到任何对象的类型信息。实际上这叙述得不是很准确。语言规范上这样描述：我们保证可以获得一个对象动态类型信息，如果该类型有至少一个虚函数。这使得RTTI数据似乎有些象virtual function talbe(虚函数表)。每个类我们只需要信息的一个拷贝，我们需要一种方法从任何包含虚函数的对象里获得合适的信息。这种 RTTI 和virtual function table 之间的相似点并不是巧合：RTTI被设计为在类的vtbl基础上实现。</div></div><div><br />例如，vtbl数组的索引 0 处可以包含一个 type_info 对象的指针，这个对象属于该vtbl相对应的类。上述C1 类的vtbl看上去象这样： <br /><img src="http://www.cppblog.com/images/cppblog_com/lovecpp666/RITI.GIF" alt="" border="0" height="176" width="538" /></div></span></div></div><img src ="http://www.cppblog.com/lovecpp666/aggbug/169375.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lovecpp666/" target="_blank">云卷云舒</a> 2012-03-29 09:49 <a href="http://www.cppblog.com/lovecpp666/articles/169375.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第四章：运算符</title><link>http://www.cppblog.com/lovecpp666/articles/169275.html</link><dc:creator>云卷云舒</dc:creator><author>云卷云舒</author><pubDate>Wed, 28 Mar 2012 07:31:00 GMT</pubDate><guid>http://www.cppblog.com/lovecpp666/articles/169275.html</guid><wfw:comment>http://www.cppblog.com/lovecpp666/comments/169275.html</wfw:comment><comments>http://www.cppblog.com/lovecpp666/articles/169275.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lovecpp666/comments/commentRss/169275.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lovecpp666/services/trackbacks/169275.html</trackback:ping><description><![CDATA[<span style="font-size: 12pt;"> </span><div><span style="font-size: 12pt; color: #ff0000;">4.1：谨慎定义类型转换函数</span><br /><br /><span style="font-size: 12pt;">&lt;1&gt;容易的方法是利用一个最新的编译器特性：explicit关键字</span><br /><br /><span style="font-size: 12pt;">&lt;2&gt;C++编译器把"&gt;&gt;"作为一个符号来解释，在两个"&gt;"间没有空格，语句会产生语法错误。</span><br /><br /><span style="font-size: 12pt;">&lt;3&gt;隐式类型转换函数</span><br /><span style="font-size: 12pt;">代码如下：</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #000000; ">template</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;T</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Array<br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;ArraySize<br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ArraySize(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;numElements):theSize(numElements)<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{}<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;size()&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;theSize;<br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;theSize;<br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;};<br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Array(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;lowBound,</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;highBound)<br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{};<br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Array(ArraySize&nbsp;size)<br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{};<br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; ">};<br /></span><span style="color: #008080; ">22</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;main()<br /></span><span style="color: #008080; ">23</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">24</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Array</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;&nbsp;a(</span><span style="color: #000000; ">10</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">25</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; "></span><span style="color: #000000; "></span></div><br /><span style="font-size: 12pt; color: #ff0000;">4.2：自增，自减操作符前缀形式和后缀形式</span><br /><br /><span style="font-size: 12pt;">&lt;1&gt;重载函数间的区别决定于它们的参数类型上的差异，但是不论increament或者decrement的前缀还是后缀都只有一个参数。为了解决这个语言问题，C++规定后缀形式有一个int类型参数，当函数被调用时，编译器传递一个0作为int参数的值给该函数。</span><br /><br /><span style="font-size: 12pt;">&lt;2&gt;前缀自增：增加然后取回</span><br /><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 后缀自增：取回然后增加</span><br /><br /><span style="font-size: 12pt;">&lt;3&gt;前缀形式</span><br /><span style="font-size: 12pt;">代码如下：<br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #000000; ">UPInt&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;UPInt::</span><span style="color: #0000FF; ">operator</span><span style="color: #000000; ">++</span><span style="color: #000000; ">()<br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">增加</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">取回值</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">}<br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;UPInt&nbsp;UPInt::</span><span style="color: #0000FF; ">operator</span><span style="color: #000000; ">++</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">)<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;UPInt&nbsp;oldValue</span><span style="color: #000000; ">=*</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">保留原值</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">++</span><span style="color: #000000; ">(</span><span style="color: #000000; ">*</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">增加</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;oldValue;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">返回原值</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">}</span></div><br /><span style="font-size: 12pt;">&lt;4&gt;后缀操作符函数没有使用它的参数。这个参数仅仅只是为了区别前缀函数调用。</span><br /><br /><span style="font-size: 12pt;">&lt;5&gt;如果在函数内部没有使用参数，许多编译器会显示警告信息。为了避免这些信息，最常用的方式就是省略掉参数名称</span><br /><br /><span style="font-size: 12pt;">&lt;6&gt;很明显后缀函数必须返回一个对象，但是为什么是const对象呢？假设不是const：</span><br /><span style="font-size: 12pt;">假设不是 const 对象，下面的代码就是正确的： </span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">1</span>&nbsp;<span style="color: #000000; ">UPInt&nbsp;&nbsp;&nbsp;i;<br /></span><span style="color: #008080; ">2</span>&nbsp;<span style="color: #000000; ">i</span><span style="color: #000000; ">++++</span><span style="color: #000000; ">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br /></span></div><span style="font-size: 12pt;"></span><span style="font-size: 12pt;">这组代码与下面的代码相同： </span><br /><span style="font-size: 12pt;">i.operator++(0).operator++(0);&nbsp; </span><br /><span style="font-size: 12pt;">很明显， 第一个调用的operator++函数返回的对象调用了第二个operator++函数。 </span><br /><span style="font-size: 12pt;">有两个理由导致我们应该厌恶上述这种做法：<br />第一是与内置类型行为不一致。当设计一个类遇到问题时，一个好的准则是使该类的行为与int 类型一致。</span><br /><span style="font-size: 12pt;">而int 类型不允许连续进行两次后缀 increment： </span><br /><span style="font-size: 12pt; color: #ff00ff;">int i; </span><br /><span style="font-size: 12pt; color: #ff00ff;">i++++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 错误! </span><br /><span style="font-size: 12pt;">第二个原因是使用两次后缀 increment 所产生的结果与调用者期望的不一致。如上所示，第二次调用operator++改变的值是第一次调用返回对象的值，</span><br /><span style="font-size: 12pt;">而不是原始对象的值。因此如果： </span><br /><span style="font-size: 12pt;">i++++; </span><br /><span style="font-size: 12pt;">是合法的，i 将仅仅增加了一次。这与人的直觉相违背，使人迷惑（对于int</span><span style="font-size: 12pt;">类型和 UPInt 都是一样）,所以最好禁止这么做。 </span><br /><span style="font-size: 12pt;">C++禁止int 类型这么做，同时你也必须禁止你自己写的类有这样的行为。</span><br /><span style="font-size: 12pt;">最容易的方法是让后缀 increment 返回 const 对象。当编译器遇到这样的代码： &nbsp;</span><br /><span style="font-size: 12pt; color: #ff00ff;">i++++;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // same as &nbsp;</span><br /><span style="font-size: 12pt; color: #ff00ff;">i.operator++(0).operator++(0); </span><br /><span style="font-size: 12pt;">它发现从第一个 operator++函数返回的 const 对象又调用 operator++函数，</span><span style="font-size: 12pt;">然而这个函数是一个 non－const 成员函数， 所以 const 对象不能调用这个函数。</span><br /><span style="font-size: 12pt;">如果你原来想过让一个函数返回 const 对象没有任何意义，现在你就知道有时还</span><span style="font-size: 12pt;">是有用的，后缀 increment和 decrement 就是例子。 （更多的例子参见 Effective </span><span style="font-size: 12pt;">C++ 条款 21） </span><br />&nbsp;<br /><span style="font-size: 12pt;">如果你很关心效率问题， 当你第一次看到后缀 increment函数时,你可能觉得</span><span style="font-size: 12pt;">有些问题。这个函数必须建立一个临时对象以做为它的返回值， （参见条款</span><span style="font-size: 12pt;">M19） ，上述实现代码建立了一个显式的临时对象（oldValue） ，这个临时对象必</span><span style="font-size: 12pt;">须被构造并在最后被析构。前缀 increment 函数没有这样的临时对象。由此得出</span><span style="font-size: 12pt;">一个令人惊讶的结论，如果仅为了提高代码效率，UPInt 的调用者应该尽量使用</span><span style="font-size: 12pt;">前缀 increment，少用后缀 increment，除非确实需要使用后缀 increment。让我</span><span style="font-size: 12pt;">们明确一下，当处理用户定义的类型时，尽可能地使用前缀 increment，因为它</span><span style="font-size: 12pt;">的效率较高。 </span><br />&nbsp;<br /><span style="font-size: 12pt;">我们再观察一下后缀与前缀 increment 操作符。它们除了返回值不同外，所完成的功能是一样的，即值加一。简而言之，它们被认为功能一样。那么你如何确保后缀increment和前缀increment的行为一致呢？当不同的程序员去维护和升级代码时，有什么能保证它们不会产生差异？除非你遵守上述代码里的原则，这才能得到确保。 这个原则是后缀 increment和 decrement 应该根据它们的前缀形式来实现。你仅仅需要维护前缀版本，因为后缀形式自动与前缀形式的行为一</span><span style="font-size: 12pt;">致。 </span><br />&nbsp;<br /><span style="font-size: 12pt;">正如你所看到的，掌握前缀和后缀 increment和decrement 是容易的。一旦了解了他们正确的返回值类型以及后缀操作符应该以前缀操作符为基础来实现的规则，就足够了。 </span><br /><br /><span style="font-size: 12pt; color: #ff0000;">4.3：不要重载&#8220;&amp;&amp;&#8221;，&#8220;||&#8221;，或&#8220;，&#8221;</span><br /><span style="font-size: 12pt;">&lt;1&gt;char *p;&nbsp; if((p!=0)&amp;&amp;(strlen(p)&gt;10))......</span><br /><span style="font-size: 12pt;">注意这个if条件的写法顺序</span><br /><br /><span style="font-size: 12pt;">&lt;2&gt;运算符重载要求：</span><br /><img src="http://www.cppblog.com/images/cppblog_com/lovecpp666/重载须知.GIF" alt="" border="0" height="340" width="575" /><br /><br /><span style="font-size: 12pt; color: #ff0000;">4.4：理解各种不同含义的new和delete</span><br /><span style="font-size: 12pt;">&lt;1&gt;new&nbsp; operator 称为new操作符与operator&nbsp; new称为new操作</span><br /><span style="font-size: 12pt;">string&nbsp; *ps = new string("Memory&nbsp; Management");</span><br /><span style="font-size: 12pt;">使用的是new operator ,即就是new操作符，这种用法是不可改变的，功能总是相同的。<br />完成两部分任务：第一，分配足够的内存以便容纳所需类型的对象；第二，它调用构造函数初始化内存中的对象。</span><br /><span style="font-size: 12pt;">而我们所能改变的是如何为对象分配内存。<br />new操作符调用一个函数来完成必需的内存分配，你能够重写或重载这个函数来改变它的行为。<br /><br />new操作符为分配内存所调用函数的名字是 operator new。</span><br /><span style="font-size: 12pt;">原型如下：</span><br /><span style="font-size: 12pt;">void&nbsp; * operator new(size_t&nbsp; size);</span><br /><span style="font-size: 12pt;">调用形式与其他函数一样：</span><br /><span style="font-size: 12pt;">void&nbsp; *rawMemory=operator&nbsp; new(sizeof(string));</span><br /><br /><span style="font-size: 12pt;">placement new</span><span style="font-size: 12pt;">旨在完成一种情况，那就是假如我们已经申请到了内存，想要在该内存上构建对象，就选择placement&nbsp; new</span><br /><span style="font-size: 12pt;">三种情况代码如下：<br /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #000000; ">#include</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">iostream</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;std;<br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;&nbsp;Test<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;a;<br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Test(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;data</span><span style="color: #000000; ">=</span><span style="color: #000000; ">10</span><span style="color: #000000; ">):a(data)<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Construction&nbsp;:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">~</span><span style="color: #000000; ">Test()<br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Destroy&nbsp;:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;<br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;};<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">};<br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;&nbsp;main()<br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">new操作符(new&nbsp;operator)</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Test&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">pa</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Test[</span><span style="color: #000000; ">2</span><span style="color: #000000; ">];&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">完成两部分任务</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;[]pa;<br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;pa</span><span style="color: #000000; ">=</span><span style="color: #000000; ">NULL;<br /></span><span style="color: #008080; ">22</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">23</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">new函数(operator&nbsp;&nbsp;new)&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">24</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">pb</span><span style="color: #000000; ">=</span><span style="color: #0000FF; ">operator</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">sizeof</span><span style="color: #000000; ">(Test));&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">仅仅只是分配一块内存，类似于malloc</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">25</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp; operator&nbsp; delete(pb);<br /></span><span style="color: #008080; ">26</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;pb</span><span style="color: #000000; ">=</span><span style="color: #000000; ">NULL;<br /></span><span style="color: #008080; ">27</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">28</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">placement&nbsp;new&nbsp;</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">29</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">suffer</span><span style="color: #000000; ">=</span><span style="color: #000000; ">malloc(</span><span style="color: #0000FF; ">sizeof</span><span style="color: #000000; ">(Test));&nbsp;&nbsp;<br /></span><span style="color: #008080; ">30</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;Test&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">pc</span><span style="color: #000000; ">=</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">(suffer)&nbsp;&nbsp;Test(</span><span style="color: #000000; ">100</span><span style="color: #000000; ">);&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">在已经申请的内存上建立自己的对象</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">31</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;pc</span><span style="color: #000000; ">-&gt;~</span><span style="color: #000000; ">Test();<br /></span><span style="color: #008080; ">32</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;free(suffer);<br /></span><span style="color: #008080; ">33</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;suffer</span><span style="color: #000000; ">=</span><span style="color: #000000; ">NULL;<br /></span><span style="color: #008080; ">34</span>&nbsp;<span style="color: #000000; ">}</span></div><span style="font-size: 12pt; color: #ff0000;">总结：</span><br /><span style="font-size: 12pt; color: #0000ff;">如果想在堆上创建一个对象，应该用new操作符，它分配内存，同时又为对象调用构造函数。</span><br /><span style="font-size: 12pt; color: #0000ff;">如果仅仅想分配内存，就用operator new函数，它不会调用构造函数</span><br /><span style="font-size: 12pt; color: #0000ff;">如果你想定制自己的在堆对象被建立时的内存分配过程，应该重载写你自己的operator new函数，new操作符会调用你定制的operator new</span><br /><span style="font-size: 12pt; color: #0000ff;">如果想在一块已经分配好的内存里建立一个对象，使用placement new</span><br /><br /><span style="font-size: 12pt;">&lt;2&gt;delete操作符与operator delete的关系与new操作符与operator&nbsp; new</span><span style="font-size: 12pt;">的关系一样</span><br /><span style="font-size: 12pt;">delete&nbsp; p;</span><br /><span style="font-size: 12pt;">导致编译器生成类似的代码：</span><br /><span style="font-size: 12pt;">p-&gt;~Class();</span><br /><span style="font-size: 12pt;">operator&nbsp; delete(p);</span><br /></div><img src ="http://www.cppblog.com/lovecpp666/aggbug/169275.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lovecpp666/" target="_blank">云卷云舒</a> 2012-03-28 15:31 <a href="http://www.cppblog.com/lovecpp666/articles/169275.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第三章：基础议题</title><link>http://www.cppblog.com/lovecpp666/articles/169248.html</link><dc:creator>云卷云舒</dc:creator><author>云卷云舒</author><pubDate>Wed, 28 Mar 2012 02:26:00 GMT</pubDate><guid>http://www.cppblog.com/lovecpp666/articles/169248.html</guid><wfw:comment>http://www.cppblog.com/lovecpp666/comments/169248.html</wfw:comment><comments>http://www.cppblog.com/lovecpp666/articles/169248.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lovecpp666/comments/commentRss/169248.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lovecpp666/services/trackbacks/169248.html</trackback:ping><description><![CDATA[<span style="font-size: 12pt;">3.1:指针与引用的区别</span><br /><span style="font-size: 12pt;">&lt;1&gt;指针用操作符&#8220;*&#8221;和&#8220;-&gt;&#8221;;引用使用操作符&#8220;.&#8221;</span><br /><span style="font-size: 12pt;">&lt;2&gt;任何时候都不能使用指向空值的引用。即就是一个引用必须总是要指向某个对象</span><br /><span style="font-size: 12pt;">通俗一点，就是说，如果你的设计不允许变量为空，这时就把变量声明为引用</span><br /><span style="font-size: 12pt;">&lt;3&gt;不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指针的要高</span><br /><span style="font-size: 12pt;">&lt;4&gt;未初始化的指针合法但危险</span><br /><span style="font-size: 12pt;">&lt;5&gt;指针应该总是被测试</span><br /><span style="font-size: 12pt;">&lt;6&gt;指针与引用的重要区别在于：指针可以被重新赋值以指向另一个不同的对象</span><br /><span style="font-size: 12pt;">&lt;7&gt;当你重载某个操作符时，应该使用引用</span><br /><span style="font-size: 12pt;">&lt;8&gt;考虑到存在不指向任何对象的可能时使用指针</span><br /><span style="font-size: 12pt;">&lt;9&gt;能够在不同的时刻指向不同的对象时使用指针</span><br /><br /><span style="font-size: 12pt;">3.2：尽量使用C++风格的类型转换</span><br /><span style="font-size: 12pt;">&lt;1&gt;四个操作符：static_cast,const_cast,dynamic_cast,reinterpret_cast</span><br /><span style="font-size: 12pt;">&lt;2&gt;使用写法：</span><br /><span style="font-size: 12pt;">static_casr&lt;type&gt;(expression)</span><br /><span style="font-size: 12pt;">&lt;3&gt;static_cast不可以把struct转换成int或者把double类型转换为指针类型</span><br /><span style="font-size: 12pt;">&lt;4&gt;static_cast不能从表达式中去除const属性</span><br /><span style="font-size: 12pt;">&lt;5&gt;const_cast用于类型转换掉表达式的const或者volatilenness属性</span><br /><span style="font-size: 12pt;">&lt;6&gt;dynamic_cast用于安全的沿着类的继承关系向下进行类型转换。即就是：能用dynamic_cast把指向基类的指针或者引用转换成指向其派生类或其兄弟类的指针或者引用</span><br /><span style="font-size: 12pt;">&lt;7&gt;danamic_cast失败转换将返回空指针</span><br /><span style="font-size: 12pt;">&lt;8&gt;如果你想没有继承关系的类型中进行转换，你可能想到static_cast</span><br /><span style="font-size: 12pt;">&lt;9&gt;如果是为了去除cosnt,你总得用const_cast</span><br /><span style="font-size: 12pt;">&lt;10&gt;使用reinterpret_cast操作符的类型转换，其转换结果几乎都是执行期定义，因此，使用这个的代码很难移植</span><br /><span style="font-size: 12pt;">&lt;11&gt;reinterpret_cast的最普通的用途就是在函数指针类型之间进行转换</span><br /><span style="font-size: 12pt;">&lt;12&gt;不到万不得已的情况不要使用reinterpret_cast</span><br /><br /><span style="font-size: 12pt;">3.3：不要对数组使用多态</span><br /><br /><span style="font-size: 12pt;">3.4：避免无用的缺省构造函数</span><br /><span style="font-size: 12pt;">&lt;1&gt;缺省构造函数就是每个类中在程序员没有定义任何构造函数的情况之下，系统为类添加的那个默认的无参构造函数</span><br /><span style="font-size: 12pt;">&lt;2&gt;一个类没有缺省构造函数。在以下二种情况下使用，会遇到问题：</span><br /><span style="font-size: 12pt;">第一：建立数组</span><br /><span style="font-size: 12pt;">NoConClass   Array[10];</span><br /><span style="font-size: 12pt;">第二：</span><br /><span style="font-size: 12pt;">NoConClass  *p=new  NoConClass[10];</span><br /><span style="font-size: 12pt;">&lt;3&gt;虚基类的缺省构造函数问题</span><img src ="http://www.cppblog.com/lovecpp666/aggbug/169248.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lovecpp666/" target="_blank">云卷云舒</a> 2012-03-28 10:26 <a href="http://www.cppblog.com/lovecpp666/articles/169248.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>