﻿<?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++博客-雨前-随笔分类-C++</title><link>http://www.cppblog.com/mildforest/category/15818.html</link><description>以后开始搞游戏开发了</description><language>zh-cn</language><lastBuildDate>Wed, 11 May 2011 19:11:32 GMT</lastBuildDate><pubDate>Wed, 11 May 2011 19:11:32 GMT</pubDate><ttl>60</ttl><item><title>muduo学习笔记2</title><link>http://www.cppblog.com/mildforest/archive/2011/05/09/146060.html</link><dc:creator>Jokey Pretty</dc:creator><author>Jokey Pretty</author><pubDate>Mon, 09 May 2011 15:16:00 GMT</pubDate><guid>http://www.cppblog.com/mildforest/archive/2011/05/09/146060.html</guid><wfw:comment>http://www.cppblog.com/mildforest/comments/146060.html</wfw:comment><comments>http://www.cppblog.com/mildforest/archive/2011/05/09/146060.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mildforest/comments/commentRss/146060.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mildforest/services/trackbacks/146060.html</trackback:ping><description><![CDATA[在服务器端，既需要维护连接的信息，连接发生变化时，还应能通知上面应用层，因此对于事件驱动的服务器，会有各种回调。<br /><br />muduo中服务器端连接的关闭：<br /><br />连接关闭的事件来源：<br /><br />1、底层网络断开，如客户端断开连接，或线路断开，则会在epoll中检测到POLLHUP，Channel在handle该event时，执行closeCallBack回调，从而调用TcpConnection::handleClose();<br /><pre>  TcpConnection::handleClose()</pre><pre>    <font color="#00cc00">将自身状态设置为kDisconnected;</font></pre><pre><font color="#00cc00">    禁用Channel的读写；</font></pre><pre><font color="#00cc00">    进行connectionCallback_回调：</font></pre><pre>        connectionCallback_由TcpServer指定，而在TcpServer中connectionCallback_又由用户指定，<br />        因此它实际上是用来通知上层应用程序，连接即将关闭，请进行相关处理；</pre><pre>    <font color="#00cc00">进行closeCallback_回调：</font></pre><pre>        closeCallback_实际上绑定的是TcpServer::removeConnection，也就是TcpServer对TcpConnection的管理。</pre><pre>        首先从连接表中删除该连接，然后在通知TcpConnection对象，你已经从TcpServer中移除了，<br />        请自身再做一些处理，即调用TcpConnection::connectDestroyed()（从EventLoop中删除自身所对应的Channel）。</pre><pre>        closeCallback_放在最后一行执行并用shared_ptr保护起来，使得函数调用完毕、TcpServer中移除了对其的引用后，<br />        自身的内存能得到释放（shared_ptr的引用计数为1）。</pre>POLLHUP event retrieved<br />    -&gt; Channel::handleEvent<br />    -&gt; Channel::handleEventWithGuard<br />        -&gt; Channel::closeCallback_()<br />        -&gt; TcpConnection::handleClose()<br />            -&gt; Set State to kDisconnected<br />            -&gt; Disable channel<br />            -&gt; connectionCallback_() (customed by application layer)<br />            -&gt; closeCallback_()<br />                -&gt; erase from ConnectionMap<br />                -&gt; TcpConnection::connectDestroyed<br />                    -&gt; remove channel from eventloop<br /><br /><br />2、服务器自身的关闭：<br />    为了优雅的关闭连接，在TcpServer中的析构函数中，会将连接标中的连接一一关闭。因为不同的TcpConnection可能存在于不同IO线程中，因此需要在对应的线程关闭TcpConnection，关闭方法是直接调用TcpConnection::connectDestroyed方法。因为此时TcpConnection此时可能仍然active，因此需要在TcpConnection::connectDestroyed中判断，如果仍avtive则先设置kDisconnected状态，禁用Channel，然后通知应用层。<img src ="http://www.cppblog.com/mildforest/aggbug/146060.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mildforest/" target="_blank">Jokey Pretty</a> 2011-05-09 23:16 <a href="http://www.cppblog.com/mildforest/archive/2011/05/09/146060.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用autotools为westworld生成makefile - 备忘录</title><link>http://www.cppblog.com/mildforest/archive/2011/03/24/142650.html</link><dc:creator>Jokey Pretty</dc:creator><author>Jokey Pretty</author><pubDate>Thu, 24 Mar 2011 07:19:00 GMT</pubDate><guid>http://www.cppblog.com/mildforest/archive/2011/03/24/142650.html</guid><wfw:comment>http://www.cppblog.com/mildforest/comments/142650.html</wfw:comment><comments>http://www.cppblog.com/mildforest/archive/2011/03/24/142650.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mildforest/comments/commentRss/142650.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mildforest/services/trackbacks/142650.html</trackback:ping><description><![CDATA[一、开发环境<br />mild:~/program/finite-state-machine/WestWorldWithWoman2$ <font color="#ff0000">uname -a</font><br />Linux mild-F80L 2.6.35-28-generic #49-Ubuntu SMP Tue Mar 1 14:40:58 UTC 2011 i686 GNU/Linux<br /><br />mild:~/program/finite-state-machine/WestWorldWithWoman2$<font color="#000000"><font color="#ff0000">g++ --version</font></font><br />g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5<br />Copyright (C) 2010 Free Software Foundation, Inc.<br /><br />mild:~/program/finite-state-machine/WestWorldWithWoman2$ <font color="#ff0000">automake --version</font><br />automake (GNU automake) 1.11.1<br />Copyright (C) 2009 Free Software Foundation, Inc.<br /><br />mild:~/program/finite-state-machine/WestWorldWithWoman2$ <font color="#ff0000">autoconf --version</font><br />autoconf (GNU Autoconf) 2.6<br /><br />二、源文件目录结构<br />ProjectName<br />      - src<br />          - *.h, *.cpp<br /><br />三、生成步骤<br />1、mild:~/program/finite-state-machine/WestWorldWithWoman2$ <font color="#ff0000">autoscan</font>    <font color="#0000ff">//生成autoscan.log与configure.scan</font><br />     mild:~/program/finite-state-machine/WestWorldWithWoman2$ cp configure.scan configure.ac <br />     mild:~/program/finite-state-machine/WestWorldWithWoman2$ vim configure.ac <br /><div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); 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: rgb(0, 0, 0);">  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);"> #                                               </span><span style="color: rgb(128, 128, 128);">-*-</span><span style="color: rgb(0, 0, 0);"> Autoconf </span><span style="color: rgb(128, 128, 128);">-*-</span><span style="color: rgb(0, 0, 0);"><br />  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">2</span><span style="color: rgb(0, 0, 0);"> # Process this </span><span style="color: rgb(0, 0, 255);">file</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">with</span><span style="color: rgb(0, 0, 0);"> autoconf </span><span style="color: rgb(0, 0, 255);">to</span><span style="color: rgb(0, 0, 0);"> produce a configure script.<br />  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">3</span><span style="color: rgb(0, 0, 0);"> <br />  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">4</span><span style="color: rgb(0, 0, 0);"> AC_PREREQ(</span><span style="color: rgb(255, 0, 0);">[</span><span style="color: rgb(255, 0, 0);">2.67</span><span style="color: rgb(255, 0, 0);">]</span><span style="color: rgb(0, 0, 0);">)<br />  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">5</span><span style="color: rgb(0, 0, 0);"> AC_INIT(westworld, </span><span style="color: rgb(128, 0, 0); font-weight: bold;">1.2</span><span style="color: rgb(0, 0, 0);">, wenhl</span><span style="color: rgb(0, 128, 0);">@gmail</span><span style="color: rgb(0, 0, 0);">.com)  # 修改<br />  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">6</span><span style="color: rgb(0, 0, 0);"> AM_INIT_AUTOMAKE    # 添加<br />  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">7</span><span style="color: rgb(0, 0, 0);"> AC_CONFIG_SRCDIR(</span><span style="color: rgb(255, 0, 0);">[</span><span style="color: rgb(255, 0, 0);">src/main.cpp</span><span style="color: rgb(255, 0, 0);">]</span><span style="color: rgb(0, 0, 0);">) #修改<br />  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">8</span><span style="color: rgb(0, 0, 0);"> AC_CONFIG_HEADERS(</span><span style="color: rgb(255, 0, 0);">[</span><span style="color: rgb(255, 0, 0);">config.h</span><span style="color: rgb(255, 0, 0);">]</span><span style="color: rgb(0, 0, 0);">)<br />  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">9</span><span style="color: rgb(0, 0, 0);"> <br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">10</span><span style="color: rgb(0, 0, 0);"> # Checks </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);"> programs.<br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">11</span><span style="color: rgb(0, 0, 0);"> AC_PROG_CXX<br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">12</span><span style="color: rgb(0, 0, 0);"> AC_PROG_CC<br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">13</span><span style="color: rgb(0, 0, 0);"> <br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">14</span><span style="color: rgb(0, 0, 0);"> # Checks </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);"> libraries.<br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">15</span><span style="color: rgb(0, 0, 0);"> <br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">16</span><span style="color: rgb(0, 0, 0);"> # Checks </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);"> header files.<br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">17</span><span style="color: rgb(0, 0, 0);"> AC_CHECK_HEADERS(</span><span style="color: rgb(255, 0, 0);">[</span><span style="color: rgb(255, 0, 0);">unistd.h</span><span style="color: rgb(255, 0, 0);">]</span><span style="color: rgb(0, 0, 0);">)<br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">18</span><span style="color: rgb(0, 0, 0);"> <br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">19</span><span style="color: rgb(0, 0, 0);"> # Checks </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);"> typedefs, structures, </span><span style="color: rgb(128, 128, 128);">and</span><span style="color: rgb(0, 0, 0);"> compiler characteristics.<br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">20</span><span style="color: rgb(0, 0, 0);"> AC_HEADER_STDBOOL<br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">21</span><span style="color: rgb(0, 0, 0);"> AC_C_INLINE<br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">22</span><span style="color: rgb(0, 0, 0);"> <br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">23</span><span style="color: rgb(0, 0, 0);"> # Checks </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);"> library functions.<br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">24</span><span style="color: rgb(0, 0, 0);"> AC_CHECK_FUNCS(</span><span style="color: rgb(255, 0, 0);">[</span><span style="color: rgb(255, 0, 0);">sqrt</span><span style="color: rgb(255, 0, 0);">]</span><span style="color: rgb(0, 0, 0);">)<br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">25</span><span style="color: rgb(0, 0, 0);"> <br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">26</span><span style="color: rgb(0, 0, 0);"> AC_CONFIG_FILES(</span><span style="color: rgb(255, 0, 0);">[</span><span style="color: rgb(255, 0, 0);">Makefile src/Makefile</span><span style="color: rgb(255, 0, 0);">]</span><span style="color: rgb(0, 0, 0);">)  #修改<br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">27</span><span style="color: rgb(0, 0, 0);"> <br /> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">28</span><span style="color: rgb(0, 0, 0);"> AC_OUTPUT <br /></span></div><br /><br />2、mild:~/program/finite-state-machine/WestWorldWithWoman2$ <font color="#ff0000">aclocal</font>     <font color="#0000ff">//生成aclocal.m4与autom4te.cache文件</font><br />     mild:~/program/finite-state-machine/WestWorldWithWoman2$ <font color="#ff0000">autoheader</font>   <font color="#0000ff">//生成config.h.in文件</font><br />3、添加Makefile.am、src/Makefile.am<br /><br />Makefile.am<br /><div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); 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: rgb(0, 0, 0);">  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);"> AUTOMAKE_OPTIONS</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 255);">foreign</span><span style="color: rgb(0, 0, 0);"><br />  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">2</span><span style="color: rgb(0, 0, 0);"> SUBDIRS </span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 0);"> src<br /></span></div><br />src/Makefile.am<br /><div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); 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: rgb(0, 0, 0);">  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);"> bin_PROGRAMS</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 0);">westworld<br />  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">2</span><span style="color: rgb(0, 0, 0);"> westworld_SOURCES</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 0);">BaseGameEntity.cpp \<br />  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">3</span><span style="color: rgb(0, 0, 0);">     main.cpp                         \<br />  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">4</span><span style="color: rgb(0, 0, 0);">     Miner.cpp                        \<br />  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">5</span><span style="color: rgb(0, 0, 0);">     MinerOwnedStates.cpp             \<br />  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">6</span><span style="color: rgb(0, 0, 0);">     MinersWife.cpp                   \<br />  </span><span style="color: rgb(128, 0, 0); font-weight: bold;">7</span><span style="color: rgb(0, 0, 0);">     MinersWifeOwnedStates.cpp   <br />                                      </span></div><br />4、mild:~/program/finite-state-machine/WestWorldWithWoman2$ <font color="#ff0000">automake --add-missing  </font><font color="#0000ff">//生成install-sh, missing, depcomp文件</font><br />5、mild:~/program/finite-state-machine/WestWorldWithWoman2$ <font color="#ff0000">autoconf</font>   <font color="#0000ff">//生成configure脚本</font><br />6、mild:~/program/finite-state-machine/WestWorldWithWoman2$ <font color="#ff0000">./configure </font><br /><br />四、make、make install...<br /><br />五、深入了解autotools。<br /><br /><a target="_blank" href="/Files/mildforest/westworld.tar.gz">源码工程下载</a><br /><br />六、参考<br /><br />http://hi.baidu.com/yzkuang/blog/item/557e4f24423d8136c9955908.html<br />http://blogold.chinaunix.net/u1/51541/showart_2255373.html<br /><br /><br /><img src ="http://www.cppblog.com/mildforest/aggbug/142650.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mildforest/" target="_blank">Jokey Pretty</a> 2011-03-24 15:19 <a href="http://www.cppblog.com/mildforest/archive/2011/03/24/142650.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>有限状态机FSM学习</title><link>http://www.cppblog.com/mildforest/archive/2011/03/24/142638.html</link><dc:creator>Jokey Pretty</dc:creator><author>Jokey Pretty</author><pubDate>Thu, 24 Mar 2011 04:41:00 GMT</pubDate><guid>http://www.cppblog.com/mildforest/archive/2011/03/24/142638.html</guid><wfw:comment>http://www.cppblog.com/mildforest/comments/142638.html</wfw:comment><comments>http://www.cppblog.com/mildforest/archive/2011/03/24/142638.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mildforest/comments/commentRss/142638.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mildforest/services/trackbacks/142638.html</trackback:ping><description><![CDATA[主要参考学习了三篇文章：<br /><br />1、<a target="_blank" title="http://www.bigfatalien.com/?p=125" href="http://www.bigfatalien.com/?p=125">A Simple C++ Finite State Machine</a><br />2、<a href="http://www.vimer.cn/2011/01/%e6%9c%89%e9%99%90%e7%8a%b6%e6%80%81%e6%9c%ba%e7%9a%84c%e5%ae%9e%e7%8e%b01-epoll%e7%8a%b6%e6%80%81%e6%9c%ba.html" title="有限状态机的C++实现(1)-epoll状态机">有限状态机的C++实现(1)-epoll状态机</a><br />3、<a target="_blank" href="http://www.ai-junkie.com/architecture/state_driven/tut_state1.html">State-Driven Game Agent Design</a><br /><br />第一篇中，提供了State接口和StateMachine类。State接口包括了进入状态、执行状态、离开状态时应该做的事情，根据具体需要继承State接口，实现具体的状态类。StateMachine类中提供了状态转移的方法和状态更新的方法：TransitionTo, Update。更新帧时，执行Update，从而执行State接口中的Process方法，可能改变当前的状态，即调用TrainsitionTo方法。<br /><br />第二篇中，提供了State接口和Actor接口、BaseActor类，没有StateMachine类。状态转移和状态执行都在Actor的ChangeState中执行。引入Actor可以使State被不同的对象拥有。<br /><br />第三篇中，提供了State接口、StateMachine类模版、Actor(Miner)，主要面向游戏中的AI。其中，每个Actor拥有一个StateMachine，StateMachine控制了State的流转。更新Actor时，将委托StateMachine进行State的更新和执行。另外，State接口也模版化，参数为Actor，从而State在执行时可以调用Actor的成员方法，即做出具体的行为。本文中具体的State采用了单例实现，因此无法保存Actor的信息。<br /><br />根据不同的具体需求，状态机也可以有不同的实现，前三者中，第三个比较清晰，比较容易把握和改造。<br /><img src ="http://www.cppblog.com/mildforest/aggbug/142638.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mildforest/" target="_blank">Jokey Pretty</a> 2011-03-24 12:41 <a href="http://www.cppblog.com/mildforest/archive/2011/03/24/142638.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[导入]pImpl Idiom</title><link>http://www.cppblog.com/mildforest/archive/2010/08/07/137868.html</link><dc:creator>Jokey Pretty</dc:creator><author>Jokey Pretty</author><pubDate>Sat, 07 Aug 2010 14:58:00 GMT</pubDate><guid>http://www.cppblog.com/mildforest/archive/2010/08/07/137868.html</guid><wfw:comment>http://www.cppblog.com/mildforest/comments/137868.html</wfw:comment><comments>http://www.cppblog.com/mildforest/archive/2010/08/07/137868.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mildforest/comments/commentRss/137868.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mildforest/services/trackbacks/137868.html</trackback:ping><description><![CDATA[
在读《Effective C++》和项目源代码时，看到pImpl Idiom。它可以用来<font color="#ff0000">降低文件间的编译依赖关系</font>，通过把一个Class分成两个Class，一个只提供接口，另一个负责实现该接口，实现接口与实现的分离。这个分离的关键在于&#8220;以声明的依赖性&#8221;替换&#8220;定义的依赖性&#8221;，而编译依赖性最小化的本质是:让头文件尽可能的自我满足，万一做不到，则让它与其他文件内的声明式（而非定义式）相依。<br><br>引用<a target="_blank" title="这里" href="http://c2.com/cgi/wiki?PimplIdiom">这里</a>的一些描述：<br><font face="Verdana">The Pimpl idiom, also known as the compilation firewall or Cheshire Cat 
technique, is a "private implementation" technique useful only in <a href="http://c2.com/cgi/wiki?CeePlusPlus">CeePlusPlus</a> and statically compiled languages like it...
</font><br><font face="Verdana"><br>Benefits:
</font><ol><li><font face="Verdana"> Changing private member variables of a class does not require recompiling classes that depend on it, thus <strong>make</strong> times are faster, and the <a href="http://c2.com/cgi/wiki?FragileBinaryInterfaceProblem">FragileBinaryInterfaceProblem</a> is reduced.
</font></li><li><font face="Verdana"> The header file does not need to #include classes that are used 'by value' in private member variables, thus <strong>compile</strong></font> times are faster.
</li><li><font face="Verdana"> This is sorta like the way <a href="http://c2.com/cgi/wiki?SmallTalk">SmallTalk</a> automatically handles classes... more pure encapsulation.
</font></li></ol><font face="Verdana">
Drawbacks:
</font><ol><li><font face="Verdana"> More work for the implementor.
</font></li><li><font face="Verdana"> Doesn't work for 'protected' members where access by subclasses is required.
</font></li><li><font face="Verdana"> Somewhat harder to read code, since some information is no longer in the header file.
</font></li><li><font face="Verdana"> Run-time performance is slightly compromised due to the 
pointer indirection, especially if function calls are virtual (branch 
prediction for indirect branches is generally poor).
</font></li></ol><font face="Verdana">
How to do it:
</font><ol><li><font face="Verdana"> Put all the private member variables into a struct.
</font></li><li><font face="Verdana"> Put the struct definition in the .cpp file.
</font></li><li><font face="Verdana"> In the header file, put only the <a href="http://c2.com/cgi/wiki?ForwardDeclaration">ForwardDeclaration</a> of the struct.
</font></li><li><font face="Verdana"> In the class definition, declare a (smart) pointer to the struct as the only private member variable.
</font></li><li><font face="Verdana"> The constructors for the class need to create the struct.
</font></li><li><font face="Verdana"> The destructor of the class needs to destroy the struct (possibly implicitly due to use of a smart pointer).
</font></li><li><font face="Verdana"> The assignment operator and <a href="http://c2.com/cgi/wiki?CopyConstructor">CopyConstructor</a> need to copy the struct appropriately or else be disabled.
</font></li></ol><font face="Verdana">Code：</font><font face="Courier New"><br><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; width: 98%; "><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><font face="Courier New"><span style="color: rgb(0, 128, 128);">1</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">struct</span><span style="color: rgb(0, 0, 0);">&nbsp;AImp;<br></span><span style="color: rgb(0, 128, 128);">2</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;A&nbsp;{<br></span><span style="color: rgb(0, 128, 128);">3</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">:<br></span><span style="color: rgb(0, 128, 128);">4</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;Same&nbsp;public&nbsp;interface&nbsp;as&nbsp;A,&nbsp;but&nbsp;all&nbsp;delegated&nbsp;to&nbsp;concrete&nbsp;implementation.</span><span style="color: rgb(0, 128, 0);"><br></span><span style="color: rgb(0, 128, 128);">5</span>&nbsp;<span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">:<br></span><span style="color: rgb(0, 128, 128);">6</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;AImp&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;pimpl;<br></span><span style="color: rgb(0, 128, 128);">7</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;};<br></span><span style="color: rgb(0, 128, 128);">8</span>&nbsp;</font><span style="color: rgb(0, 0, 0);"></span></div><br><br></font><font face="Verdana">If you use a <a href="http://c2.com/cgi/wiki?SmartPointer">SmartPointer</a>
 and you only have one implementation, there is no need to make any of 
the member functions virtual, except possibly the destructor. The 
run-time cost of non-virtual member function calls is much lower, and a 
compiler that does whole-program optimization can inline them even 
though they're in a separate translation unit. Here's an example:
</font><pre><div style="background-color: rgb(238, 238, 238); font-size: 13px; border-left-color: rgb(204, 204, 204); padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; width: 98%; "><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 128, 128);">&nbsp;1</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;foo.h</span><span style="color: rgb(0, 128, 0);"><br></span><span style="color: rgb(0, 128, 128);">&nbsp;2</span>&nbsp;<span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">&nbsp;3</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;foo_impl;<br></span><span style="color: rgb(0, 128, 128);">&nbsp;4</span>&nbsp;<span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">&nbsp;5</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;foo&nbsp;{<br></span><span style="color: rgb(0, 128, 128);">&nbsp;6</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;Boilerplate</span><span style="color: rgb(0, 128, 0);"><br></span><span style="color: rgb(0, 128, 128);">&nbsp;7</span>&nbsp;<span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;friend&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;foo_impl;<br></span><span style="color: rgb(0, 128, 128);">&nbsp;8</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;foo()&nbsp;{}&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;so&nbsp;only&nbsp;foo_impl&nbsp;can&nbsp;derive&nbsp;from&nbsp;foo</span><span style="color: rgb(0, 128, 0);"><br></span><span style="color: rgb(0, 128, 128);">&nbsp;9</span>&nbsp;<span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">&nbsp;foo_impl&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;impl()&nbsp;</span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">;<br></span><span style="color: rgb(0, 128, 128);">10</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;foo_impl&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;impl();<br></span><span style="color: rgb(0, 128, 128);">11</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">:<br></span><span style="color: rgb(0, 128, 128);">12</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">virtual</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">~</span><span style="color: rgb(0, 0, 0);">foo()&nbsp;{}<br></span><span style="color: rgb(0, 128, 128);">13</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;Factories</span><span style="color: rgb(0, 128, 0);"><br></span><span style="color: rgb(0, 128, 128);">14</span>&nbsp;<span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;std::auto_ptr</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">foo</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;create(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;value);<br></span><span style="color: rgb(0, 128, 128);">15</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;Interface</span><span style="color: rgb(0, 128, 0);"><br></span><span style="color: rgb(0, 128, 128);">16</span>&nbsp;<span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;value()&nbsp;</span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">;<br></span><span style="color: rgb(0, 128, 128);">17</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;};<br></span><span style="color: rgb(0, 128, 128);">18</span>&nbsp;<span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">19</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;foo.cpp</span><span style="color: rgb(0, 128, 0);"><br></span><span style="color: rgb(0, 128, 128);">20</span>&nbsp;<span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">21</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;foo_impl&nbsp;:&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;foo&nbsp;{<br></span><span style="color: rgb(0, 128, 128);">22</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;friend&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;foo;<br></span><span style="color: rgb(0, 128, 128);">23</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;Constructors&nbsp;mirroring&nbsp;the&nbsp;factory&nbsp;functions&nbsp;in&nbsp;foo</span><span style="color: rgb(0, 128, 0);"><br></span><span style="color: rgb(0, 128, 128);">24</span>&nbsp;<span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">explicit</span><span style="color: rgb(0, 0, 0);">&nbsp;foo_impl(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;value)&nbsp;:&nbsp;value_(value)&nbsp;{}<br></span><span style="color: rgb(0, 128, 128);">25</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;Member&nbsp;data</span><span style="color: rgb(0, 128, 0);"><br></span><span style="color: rgb(0, 128, 128);">26</span>&nbsp;<span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;value_;<br></span><span style="color: rgb(0, 128, 128);">27</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;};<br></span><span style="color: rgb(0, 128, 128);">28</span>&nbsp;<span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">29</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;inline&nbsp;</span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">&nbsp;foo_impl&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;foo::impl()&nbsp;</span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">&nbsp;{<br></span><span style="color: rgb(0, 128, 128);">30</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;static_cast</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">&nbsp;foo_impl&nbsp;</span><span style="color: rgb(0, 0, 0);">*&gt;</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">);<br></span><span style="color: rgb(0, 128, 128);">31</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;}<br></span><span style="color: rgb(0, 128, 128);">32</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;inline&nbsp;foo_impl&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;foo::impl()&nbsp;{<br></span><span style="color: rgb(0, 128, 128);">33</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;static_cast</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">foo_impl&nbsp;</span><span style="color: rgb(0, 0, 0);">*&gt;</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">);<br></span><span style="color: rgb(0, 128, 128);">34</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;}<br></span><span style="color: rgb(0, 128, 128);">35</span>&nbsp;<span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">36</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;std::auto_ptr</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">foo</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;foo::create(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;value)&nbsp;{<br></span><span style="color: rgb(0, 128, 128);">37</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;std::auto_ptr</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">foo</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;foo_impl(value));<br></span><span style="color: rgb(0, 128, 128);">38</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;}<br></span><span style="color: rgb(0, 128, 128);">39</span>&nbsp;<span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">40</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;foo::value()&nbsp;</span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">&nbsp;{&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;impl()</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">value_;&nbsp;}<br></span><span style="color: rgb(0, 128, 128);">41</span>&nbsp;<span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 128, 128);">42</span>&nbsp;<span style="color: rgb(0, 0, 0);"></span></div><br></pre><font face="Verdana">Here, the destructor needs to be declared virtual foo so that 
std::auto_ptr&lt;foo&gt; calls foo_impl's destructor. If you use 
boost::shared_ptr&lt;foo&gt; instead, even that doesn't need to be 
virtual, because shared_ptr remembers how to call the correct 
destructor. (This doesn't improve performance or memory use, because 
shared_ptr is larger and slower than auto_ptr, but if you need to use 
shared_ptr anyway you may as well eliminate the virtual destructor.) -- <a href="http://c2.com/cgi/wiki?BenHutchings">BenHutchings</a></font><br><br><br>参考阅读：<br><br>Effective C++<br>http://c2.com/cgi/wiki?PimplIdiom<br>http://en.wikipedia.org/wiki/Opaque_pointer<br><img src="http://www.blogjava.net/wenhl5656/aggbug/328217.html" width="1" height="1"><br><br><div align="right"><a style="text-decoration:none;" href="http://www.blogjava.net/wenhl5656/" target="_blank">CodeLoser</a> 2010-08-07 22:58 <a href="http://www.blogjava.net/wenhl5656/archive/2010/08/07/328217.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div><br>文章来源:<a href="http://www.blogjava.net/wenhl5656/archive/2010/08/07/328217.html">http://www.blogjava.net/wenhl5656/archive/2010/08/07/328217.html</a><img src ="http://www.cppblog.com/mildforest/aggbug/137868.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mildforest/" target="_blank">Jokey Pretty</a> 2010-08-07 22:58 <a href="http://www.cppblog.com/mildforest/archive/2010/08/07/137868.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[导入]Effective C++ -  09.绝对不要在构造和析构过程中调用虚函数</title><link>http://www.cppblog.com/mildforest/archive/2010/07/28/137869.html</link><dc:creator>Jokey Pretty</dc:creator><author>Jokey Pretty</author><pubDate>Wed, 28 Jul 2010 13:37:00 GMT</pubDate><guid>http://www.cppblog.com/mildforest/archive/2010/07/28/137869.html</guid><wfw:comment>http://www.cppblog.com/mildforest/comments/137869.html</wfw:comment><comments>http://www.cppblog.com/mildforest/archive/2010/07/28/137869.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mildforest/comments/commentRss/137869.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mildforest/services/trackbacks/137869.html</trackback:ping><description><![CDATA[

		<font face="Verdana">要点：绝对不应该在构造函数和析构函数中调用虚函数。<br><br>Derived Class对象内的Base Class成分会在Derived Class自身成分被构造之前构造完成。如果Base Class构造函数中有虚函数（virtual function），该virtual function绝对不会下降到Derived Class层中，而是直接调用Base Class中该函数，通俗的说，即——在Base Class构造时，virtual function不再被当成virtual function。<br><br>这是因为，在Base Class构造期间，对象的类型是Base Class而不是Derived Class。不只是虚函数会被编译器解析至Base Class中，若使用运行期类信息（runtime type information，例如dynamic_cast和typeid），也会把对象视为Base Class类型。同样这也适合于析构函数。一旦由Derived Class的析构函数进入到BaseClass的析构函数后，对象就成为一个BaseClass的对象了。<br></font>
<img src="http://www.blogjava.net/wenhl5656/aggbug/327365.html" width="1" height="1"><br><br><div align="right"><a style="text-decoration:none;" href="http://www.blogjava.net/wenhl5656/" target="_blank">CodeLoser</a> 2010-07-28 21:37 <a href="http://www.blogjava.net/wenhl5656/archive/2010/07/28/327365.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div><br>文章来源:<a href="http://www.blogjava.net/wenhl5656/archive/2010/07/28/327365.html">http://www.blogjava.net/wenhl5656/archive/2010/07/28/327365.html</a><img src ="http://www.cppblog.com/mildforest/aggbug/137869.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mildforest/" target="_blank">Jokey Pretty</a> 2010-07-28 21:37 <a href="http://www.cppblog.com/mildforest/archive/2010/07/28/137869.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>