﻿<?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>BlogJava-code loser-随笔分类-C++</title><link>http://www.blogjava.net/wenhl5656/category/45754.html</link><description>想起和老肖研究中断的日子，倍觉温馨</description><language>zh-cn</language><lastBuildDate>Mon, 09 Aug 2010 03:56:44 GMT</lastBuildDate><pubDate>Mon, 09 Aug 2010 03:56:44 GMT</pubDate><ttl>60</ttl><item><title>pImpl Idiom</title><link>http://www.blogjava.net/wenhl5656/archive/2010/08/07/328217.html</link><dc:creator>爱吃鱼头</dc:creator><author>爱吃鱼头</author><pubDate>Sat, 07 Aug 2010 14:58:00 GMT</pubDate><guid>http://www.blogjava.net/wenhl5656/archive/2010/08/07/328217.html</guid><wfw:comment>http://www.blogjava.net/wenhl5656/comments/328217.html</wfw:comment><comments>http://www.blogjava.net/wenhl5656/archive/2010/08/07/328217.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wenhl5656/comments/commentRss/328217.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wenhl5656/services/trackbacks/328217.html</trackback:ping><description><![CDATA[在读《Effective C++》和项目源代码时，看到pImpl Idiom。它可以用来<font color="#ff0000">降低文件间的编译依赖关系</font>，通过把一个Class分成两个Class，一个只提供接口，另一个负责实现该接口，实现接口与实现的分离。这个分离的关键在于“以声明的依赖性”替换“定义的依赖性”，而编译依赖性最小化的本质是:让头文件尽可能的自我满足，万一做不到，则让它与其他文件内的声明式（而非定义式）相依。<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: 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>--><font face="Courier New"><span style="color: rgb(0, 128, 128);">1</span> <span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 255);">struct</span><span style="color: rgb(0, 0, 0);"> AImp;<br /></span><span style="color: rgb(0, 128, 128);">2</span> <span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> A {<br /></span><span style="color: rgb(0, 128, 128);">3</span> <span style="color: rgb(0, 0, 0);">  </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> <span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Same public interface as A, but all delegated to concrete implementation.</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 128, 128);">5</span> <span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);">  </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> <span style="color: rgb(0, 0, 0);">    AImp </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> pimpl;<br /></span><span style="color: rgb(0, 128, 128);">7</span> <span style="color: rgb(0, 0, 0);">  };<br /></span><span style="color: rgb(0, 128, 128);">8</span> </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: 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, 128, 128);"> 1</span> <span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> foo.h</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 2</span> <span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 3</span> <span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> foo_impl;<br /></span><span style="color: rgb(0, 128, 128);"> 4</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 5</span> <span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> foo {<br /></span><span style="color: rgb(0, 128, 128);"> 6</span> <span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Boilerplate</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 7</span> <span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);">    friend </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> foo_impl;<br /></span><span style="color: rgb(0, 128, 128);"> 8</span> <span style="color: rgb(0, 0, 0);">    foo() {} </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> so only foo_impl can derive from foo</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 128, 128);"> 9</span> <span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);"> foo_impl </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> impl() </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> <span style="color: rgb(0, 0, 0);">    foo_impl </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> impl();<br /></span><span style="color: rgb(0, 128, 128);">11</span> <span style="color: rgb(0, 0, 0);">  </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> <span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 0, 255);">virtual</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">~</span><span style="color: rgb(0, 0, 0);">foo() {}<br /></span><span style="color: rgb(0, 128, 128);">13</span> <span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Factories</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 128, 128);">14</span> <span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> 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);"> create(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> value);<br /></span><span style="color: rgb(0, 128, 128);">15</span> <span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Interface</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 128, 128);">16</span> <span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> value() </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> <span style="color: rgb(0, 0, 0);">  };<br /></span><span style="color: rgb(0, 128, 128);">18</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">19</span> <span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> foo.cpp</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 128, 128);">20</span> <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> <span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> foo_impl : </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> foo {<br /></span><span style="color: rgb(0, 128, 128);">22</span> <span style="color: rgb(0, 0, 0);">    friend </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> foo;<br /></span><span style="color: rgb(0, 128, 128);">23</span> <span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Constructors mirroring the factory functions in foo</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 128, 128);">24</span> <span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 0, 255);">explicit</span><span style="color: rgb(0, 0, 0);"> foo_impl(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> value) : value_(value) {}<br /></span><span style="color: rgb(0, 128, 128);">25</span> <span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Member data</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 128, 128);">26</span> <span style="color: rgb(0, 128, 0);"></span><span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> value_;<br /></span><span style="color: rgb(0, 128, 128);">27</span> <span style="color: rgb(0, 0, 0);">  };<br /></span><span style="color: rgb(0, 128, 128);">28</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">29</span> <span style="color: rgb(0, 0, 0);">  inline </span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);"> foo_impl </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> foo::impl() </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);">30</span> <span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> 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);"> foo_impl </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> <span style="color: rgb(0, 0, 0);">  }<br /></span><span style="color: rgb(0, 128, 128);">32</span> <span style="color: rgb(0, 0, 0);">  inline foo_impl </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> foo::impl() {<br /></span><span style="color: rgb(0, 128, 128);">33</span> <span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> static_cast</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">foo_impl </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> <span style="color: rgb(0, 0, 0);">  }<br /></span><span style="color: rgb(0, 128, 128);">35</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">36</span> <span style="color: rgb(0, 0, 0);">  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);"> foo::create(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> value) {<br /></span><span style="color: rgb(0, 128, 128);">37</span> <span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> 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);"> foo_impl(value));<br /></span><span style="color: rgb(0, 128, 128);">38</span> <span style="color: rgb(0, 0, 0);">  }<br /></span><span style="color: rgb(0, 128, 128);">39</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">40</span> <span style="color: rgb(0, 0, 0);">  </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> foo::value() </span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);"> { </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> impl()</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">value_; }<br /></span><span style="color: rgb(0, 128, 128);">41</span> <span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 128, 128);">42</span> <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">爱吃鱼头</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>]]></description></item><item><title>Effective C++ -  09.绝对不要在构造和析构过程中调用虚函数</title><link>http://www.blogjava.net/wenhl5656/archive/2010/07/28/327365.html</link><dc:creator>爱吃鱼头</dc:creator><author>爱吃鱼头</author><pubDate>Wed, 28 Jul 2010 13:37:00 GMT</pubDate><guid>http://www.blogjava.net/wenhl5656/archive/2010/07/28/327365.html</guid><wfw:comment>http://www.blogjava.net/wenhl5656/comments/327365.html</wfw:comment><comments>http://www.blogjava.net/wenhl5656/archive/2010/07/28/327365.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wenhl5656/comments/commentRss/327365.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wenhl5656/services/trackbacks/327365.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">爱吃鱼头</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>]]></description></item></channel></rss>