﻿<?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++博客-白纸人生</title><link>http://www.cppblog.com/andxie99/</link><description>上学时，因我年龄最小，个头也最小，上课时，就像大猩猩堆里的猴一般。如今，这猴偶尔也把最近的一些情况写在这里。</description><language>zh-cn</language><lastBuildDate>Sat, 06 Sep 2008 17:08:36 GMT</lastBuildDate><pubDate>Sat, 06 Sep 2008 17:08:36 GMT</pubDate><ttl>60</ttl><item><title>妙语摘录</title><link>http://www.cppblog.com/andxie99/archive/2007/10/01/33303.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Mon, 01 Oct 2007 13:01:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/10/01/33303.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/33303.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/10/01/33303.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/33303.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/33303.html</trackback:ping><description><![CDATA[<br>&nbsp;&nbsp;&nbsp; 整理资料，于G:\我的秘书\妙语下发现很多平时收集的认为不错的词句，整理如下，以后也会随时更新的。<br><br>&nbsp;&nbsp;&nbsp; <strong>&#8220;大学者，非谓有大楼之谓也，有大师之谓也。&#8221;</strong>&nbsp; ——清华老校长梅贻琦的治校名言。<br><br>林锐&nbsp;&nbsp;&nbsp; 《软件工程思想》中：<br>&nbsp;&nbsp;&nbsp; <strong>就象蒸出一笼馒头，在上面插一朵鲜花，本想弄点诗情画意，却让人误以为那是一堆热气腾腾的牛粪。</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ——讲述可理解性与简洁性时用的比喻。&nbsp;<br><br>&nbsp;&nbsp;&nbsp; <strong>人分四类——人物，人才，人手，人渣。</strong>&nbsp;&nbsp;&nbsp; ——可行性分析的要素中人这一要素时的论述 <br><br>&nbsp;&nbsp;&nbsp; <strong>举杭州西湖的例子吧。西湖的一些景点收门票，卖纪念品，一年不多的经营收入，只够用来打扫卫生、修修补补、种树植草。但西湖有白居易、苏东坡巨大的贡献，千年累积的&#8220;人文、历史、地理&#8221;价值何止千百亿。假设杭州西湖上市，起价1亿元人民币，真不知道有多少人来争抢，股值当然会狂升千百倍。而我家乡的一个鱼塘也叫&#8220;西湖&#8221;，主人从来不幻想他的&#8220;西湖&#8221;值多少个亿，但他知道卖不出鱼就会贫穷，一天不争几元钱就会挨饿。</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ——论述为什么一个固定资产可以被忽略的，几乎没有营业利润的Internet企业，可以有极高的股市价值，并且市值不停上涨。 <br><br>&nbsp;&nbsp;&nbsp; <strong>我认为Java好比是C++的外甥，虽然不是直接遗传的，但也几分象样。外甥在舅舅身上玩耍时洒了一泡尿，俩人不该为此而争吵。&nbsp;&nbsp;&nbsp; </strong>——关于编程语言 <br><br>&nbsp;&nbsp;&nbsp; <strong>有一次文学考试，问高尔基是哪国人。一考生乐极而吟：&#8220;尔基啊尔基，你若不姓高，我怎知你是中国人。&#8221;这是一种瞎猜法。如果这种方法用于软件测试，人累死也测不出什么结果来。</strong>&nbsp;&nbsp;&nbsp; ——软件测试 <br><br>&nbsp;&nbsp;&nbsp; <strong>都说急中生智，我不信。我认为大多数人着急了就会蛮干，早把&#8220;智&#8221;丢到脑后。不仅人如此，动物也如此。</strong>&nbsp;&nbsp;&nbsp; ——论述软件改错时不可蛮干&nbsp;<br><br>&nbsp;&nbsp;&nbsp;<strong> 抽象是有选择的忽略。</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ——C++深思录（Ruminations on C++中文版）<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; <strong>有的情况下，现在的折衷方案比未来的理想方案好得多。</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ——C++深思录（Ruminations on C++中文版） <br><br>&nbsp;&nbsp;&nbsp; <strong>真正的专业人员会将其所有的正规训练和经验技巧都专注于每一个所输入的按键上。</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ——《C++程序调试实用手册》<br><br>&nbsp;&nbsp;&nbsp; <strong>所谓好的注释就是既不至于侮辱一个程序员的智力，也不放过对任何复杂代码的解释。&nbsp;</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ——《C++程序调试实用手册》<br><br>&nbsp;&nbsp;&nbsp; <strong>工具只有获取结果的手段，如果你只注意手段而忽视结果，那你就是在浪费时间。</strong><br>
<img src ="http://www.cppblog.com/andxie99/aggbug/33303.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-10-01 21:01 <a href="http://www.cppblog.com/andxie99/archive/2007/10/01/33303.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>聊聊封装、继承</title><link>http://www.cppblog.com/andxie99/archive/2007/07/21/28494.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 21 Jul 2007 08:18:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/07/21/28494.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/28494.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/07/21/28494.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/28494.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/28494.html</trackback:ping><description><![CDATA[&nbsp;
<p>&nbsp;</p>
<p align=left><span>&nbsp;<span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>在</span><span>C++</span><span>中封装的概念是把一个对象的外观接口同实际工作方式（实现）分离开来，但是</span><span>C++</span><span>的封装是不完全的，</span><span>编译器必须知道一个对象的所有部分的声明，以便创建和管理它。我们可以想象一种只需声明一个对象的公共接口部分的编程语言，而将私有的实现部分隐藏起来。</span><span>C + +</span><span>在编译期间要尽可能多地做静态类型检查。这意味着尽早捕获错误，也意味着程序具有更高的效率。然而这对私有的实现部分来说带来两个影响：一是即使程序员不能轻易地访问实现部分，但他可以看到它；二是造成一些不必要的重复编译<span>。</span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>然而</span><span>C++</span><span>并没有将这个原则应用到二进制层次上，这是因为</span><span>C++</span><span>的类既是描述了一个接口同时也描述了实现的过程</span><span>,</span><span>示例如下：</span></p>
<p><span>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CMyString<br><img id=Codehighlighter1_16_172_Open_Image onclick="this.style.display='none'; Codehighlighter1_16_172_Open_Text.style.display='none'; Codehighlighter1_16_172_Closed_Image.style.display='inline'; Codehighlighter1_16_172_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_16_172_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_16_172_Closed_Text.style.display='none'; Codehighlighter1_16_172_Open_Image.style.display='inline'; Codehighlighter1_16_172_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_16_172_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_16_172_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;m_cch;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">m_psz;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;CMyString(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">psz);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">CMyString();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Length()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Index(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">psz)&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p></span>&nbsp;</p>
<p>&nbsp;</p>
<p><span>CMyStirng</span><span>对外过多的暴露了内存布局实现的细节，这些信息过度的依赖于这些成员变量的大小和顺序，从而导致了客户过度依赖于可执行代码之间的二进制耦合关系，这样的接口不利于跨语言跨平台的软件开发和移植。</span></p>
<p>&nbsp;</p>
<p><strong><span>1.1.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handle-Body</span></strong><span>模式</span><strong></strong></p>
<p>&nbsp;</p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>解决这个问题的技术有一种叫句柄类（ </span><span>handle classes</span><span>）</span><span>。有关实现的任何东西都消失了，只剩一个单一的指针&#8220;</span><strong><span>m_pThis</span></strong><span>&#8221;。该指针指向一个结构，该结构的定义与其所有的成员函数的定义都出现在实现文件中。这样，只要接口部分不改变，头文件就不需变动。而实现部分可以按需要任意更动，完成后只要对实现文件进行重新编译，然后再连接到项目中。</span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面是</span></span><span>这项技术的简单例子。头文件中只包含公共的接口和一个简单的没有完全指定的类指针。</span></p>
<p align=left>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CMyStringHandle<br><img id=Codehighlighter1_22_201_Open_Image onclick="this.style.display='none'; Codehighlighter1_22_201_Open_Text.style.display='none'; Codehighlighter1_22_201_Closed_Image.style.display='inline'; Codehighlighter1_22_201_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_22_201_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_22_201_Closed_Text.style.display='none'; Codehighlighter1_22_201_Open_Image.style.display='inline'; Codehighlighter1_22_201_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_22_201_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_22_201_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CMyString；<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;CMyString&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">m_pThis;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;CMyStringHandle&nbsp;(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">psz);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">&nbsp;CMyStringHandle&nbsp;();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Length()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Index(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">psz)&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">；<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>CMyStringHandle::&nbsp;CMyStringHandle(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">psz)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>:m_pThis(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;CMyString(psz));<br><img id=Codehighlighter1_286_288_Open_Image onclick="this.style.display='none'; Codehighlighter1_286_288_Open_Text.style.display='none'; Codehighlighter1_286_288_Closed_Image.style.display='inline'; Codehighlighter1_286_288_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_286_288_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_286_288_Closed_Text.style.display='none'; Codehighlighter1_286_288_Open_Image.style.display='inline'; Codehighlighter1_286_288_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_286_288_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_286_288_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>CMyStringHandle::</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">&nbsp;CMyStringHandle()<br><img id=Codehighlighter1_328_349_Open_Image onclick="this.style.display='none'; Codehighlighter1_328_349_Open_Text.style.display='none'; Codehighlighter1_328_349_Closed_Image.style.display='inline'; Codehighlighter1_328_349_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_328_349_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_328_349_Closed_Text.style.display='none'; Codehighlighter1_328_349_Open_Image.style.display='inline'; Codehighlighter1_328_349_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_328_349_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_328_349_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;delete&nbsp;m_pThis;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;CMyStringHandle::Length()<br><img id=Codehighlighter1_382_412_Open_Image onclick="this.style.display='none'; Codehighlighter1_382_412_Open_Text.style.display='none'; Codehighlighter1_382_412_Closed_Image.style.display='inline'; Codehighlighter1_382_412_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_382_412_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_382_412_Closed_Text.style.display='none'; Codehighlighter1_382_412_Open_Image.style.display='inline'; Codehighlighter1_382_412_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_382_412_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_382_412_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;m_pThis</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Length();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;CMyStringHandle::Index(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">psz)<br><img id=Codehighlighter1_459_490_Open_Image onclick="this.style.display='none'; Codehighlighter1_459_490_Open_Text.style.display='none'; Codehighlighter1_459_490_Closed_Image.style.display='inline'; Codehighlighter1_459_490_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_459_490_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_459_490_Closed_Text.style.display='none'; Codehighlighter1_459_490_Open_Image.style.display='inline'; Codehighlighter1_459_490_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_459_490_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_459_490_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;m_pThis</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Index(psz);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p align=left>&nbsp;</p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>这是所有客户程序员都能看到的。<br></span><strong><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>class</span></strong><span> <strong><span>CMyString</span></strong></span><strong><span>；</span></strong></p>
<p align=left><span>是一个没有完全指定的类型说明或类声明（一个类的定义包含类的主体）。它告诉编译器，</span><span><span><strong>CMyString</strong></span></span><span>是一个结构的名字，但没有提供有关该结构的任何东西。这对产生一个指向结构的指针来说已经足够了。但我们在提供一个结构的主体部分之前不能创建一个对象。在这种技术里，包含具体实现的结构主体被隐藏在实现文件中。</span></p>
<p align=left>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>在设计模式中，这就叫做</span><span>Handle-Body </span><span>模式，</span><strong><span>Handle-Body</span></strong><span>只含有一个实体指针，服务的数据成员永远被封闭在服务系统中。</span></p>
<p><strong><span>Handle-Body</span></strong><span>的布局结构永远不会随着实现类数据成员的加入或者删除或者修改而导致<strong><span>Handle-Body</span></strong>的修改，即<strong><span>Handle-Body</span></strong>协议不依赖于<span>C++</span>实现类的任何细节。这就有效的对用户的编译器隐藏了这些细节，用户在使用对这项技术时候，<strong><span>Handle-Body</span></strong><span> </span>接口成了它唯一的入口。</span></p>
<p>&nbsp;</p>
<p><span>然而</span><strong><span>Handle-Body</span></strong><span>模式也有自己的弱点：</span></p>
<p><span><span>1、</span></span><span>接口类必须把每一个方法调用显示的传递给实现类，这在一个只有一个构造和一个析构的类来说显然不构成负担，但是如果一个庞大的类库，它有上百上千个方法时候，光是编写这些方法传递就有可能非常冗长，这也增加了出错的可能性。</span></p>
<p><span><span>2、</span></span><span>对于关注于性能的应用每一个方法都得有两层的函数调用，嵌套的开销也不理想</span></p>
<p><span><span>3、</span></span><span>由于句柄的存在，依然存在编译连接器兼容性问题。</span></p>
<p>&nbsp;</p>
<p><strong><span><span>1.1.2<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span></strong><strong><span>抽象接口</span></strong></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>使用了&#8220;接口与实现的分离&#8221;技术的</span><span> <strong><span>Handle-Body </span></strong></span><span>解决了编译器</span><span>/</span><span>链接器的大部分问题，而</span><span>C++</span><span>面向对象编程中的抽象接口同样是运用了&#8220;接口与实现分离&#8221;的思想，而采用抽象接口对于解决这类问题是一个极其完美的解决方案。</span></p>
<p><span><span>1、</span></span><span>抽象接口的语言描述：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>class IMyString</span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int Length() const = 0;&nbsp;//</span><span>这表示是一个纯虚函数，具有纯虚函数的接口</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int Index(const char *psz) const = 0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span><span>；</span></p>
<p>&nbsp;</p>
<p><span><span>2、</span></span><span>抽象接口的内存结构：</span></p>
<p><span></span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 抽象接口采用虚函数表来调用成员方法。&nbsp;</p>
<p><span><span>3、</span></span><span><span>&nbsp;&nbsp; </span></span><span>抽象接口的实现代码：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>接口：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span><span>class IMyString</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int Length() const = 0;&nbsp;//</span><span>这表示是一个纯虚函数，具有纯虚函数的接口</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int Index(const char *psz) const = 0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span><span>；</span></p>
</span></span>
<p><span>&nbsp;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>实现：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>class CMyString</span><span>：</span><span>public IMyString</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>private:</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;const int m_cch;</span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>char *m_psz;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>public:</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CMyString(const char *psz);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual ~CMyString();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>int Length() const;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>int Index(const char *psz) const;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>从上面采用抽象接口的实例来看，抽象接口解决了</span><span>Handle-Body</span><span>所遗留下来的全部缺陷。</span></p>
<p><span>抽象接口的一个典型应用：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>抽象工厂（</span><span>AbstractFactroy</span><span>）</span></p>
<p><strong>&nbsp;</strong></p>
<p><strong><span><span>1.2<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span></strong><strong><span>多继承与菱形缺陷、<span>this</span>跳转等</span></strong></p>
<p><span>多重继承是<span>C++</span>语言独有的继承方式，其它几乎所有语言都秉承了单一继承的思想。这是因为多重继承致命的缺陷导致的：</span></p>
<p><strong><span><span>1.2.1<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span></strong><strong><span>菱形缺陷</span></strong></p>
<p><span>当继承基类时，在派生类中就获得了基类所有的数据成员副本。假如类<span>B </span>从<span>A1</span>和<span>A2</span>两个类多重继承而来，这样<span>B</span>类就包含<span>A1</span>、<span>A2</span>类的数据成员副本。</span></p>
<p><span></span><span>考虑如果<span>A1</span>、<span>A2</span>都从某基类派生，该基类称为<span>Base</span>，现在继承关系将出现</span><span>菱形继承关系。<br></span></p>
<p><span>
<div align=center src_cetemp="/images/cppblog_com/andxie99/diamondBug.JPG"><img src="http://www.cppblog.com/images/cppblog_com/andxie99/diamondBug.JPG" border=0></div>
<br>我们<span>C++</span>语言来描述这种继承关系：</span>
<p>&#160;</p>
<p><span>class Base{</span><span>&#8230;</span><span> </span><span>&#8230;</span><span> }</span><span>；</span></p>
<p><span>class A1 :public Base {</span><span>&#8230;</span><span> </span><span>&#8230;</span><span> }</span><span>；</span></p>
<p><span>class A2 :public Base {</span><span>&#8230;</span><span> </span><span>&#8230;</span><span> }</span><span>；</span></p>
<p><span>class B :public A1,public A2 {</span><span>&#8230;</span><span> </span><span>&#8230;</span><span> }</span><span>；</span></p>
<p>&nbsp;</p>
<p><span>那么<span>A1</span>、<span>A2</span>都具有<span>Base</span>的副本。这样<span>B</span>就包含了<span>Base</span>的两个副本，副本发生了重叠，不但增加了存储空间，同时也引入了二义性。这就是菱形缺陷，菱形缺陷的两个缺陷：</span></p>
<p><span><span>1、</span></span><span>子对象重叠</span></p>
<p><span><span>2、</span></span><span>向上映射的二义性。</span></p>
<p><span>菱形缺陷的其中一种解决办法是使用虚拟继承。</span></p>
<p>&nbsp;</p>
<p><span>在<span>C++</span>世界里最广泛的使用虚拟继承解决菱形缺陷的应用便是标准<span>C++</span>的输入<span>/</span>输出<span>iostream</span>；</span></p>
<p>
<div align=center src_cetemp="/images/cppblog_com/andxie99/diamondBug01.JPG"><img src="http://www.cppblog.com/images/cppblog_com/andxie99/diamondBug01.JPG" border=0></div>
<strong><span></span></strong>
<p>&#160;</p>
<p><span></span>&nbsp;</p>
<p><strong>&nbsp;</strong></p>
<p><strong><span><span>1.2.2<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span></strong><strong><span>多重接口与方法名冲突问题（</span><span>Siamese twins</span></strong><strong><span>）</span></strong></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>对继承而来的虚函数改写很容易，但是如果是在改写一个&#8220;在两个基类都有相同原型&#8221;的虚函数情况就不那么容易了。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><strong><span>提出问题：</span></strong></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>假设汽车最大速度的接口为</span><span>ICar</span><span>，潜艇最大速度的接口为</span><span> IBoat</span><span>，有一个两栖类的交通工具它可以奔跑在马路上，也可以航行在大海中，那么它就同时拥有</span><span>ICar</span><span>、</span><span>IBoat</span><span>两种交通工具的最大速度特性，我们定义它的接口为</span><span>ICarBoat</span><span>；</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>class&nbsp;ICar</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span>&nbsp;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetMaxSpeed</span><span>（）</span><span>= 0</span><span>；</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span><span>；</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>class&nbsp;IBoat</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span>&nbsp;<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetMaxSpeed</span><span>（）</span><span>= 0</span><span>；</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span><span>；</span></p>
<p><span><span>&nbsp;&nbsp; </span></span><span>我们先对</span><span>ICarBoat</span><span>的接口做一个尝试：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>class CCarBoat</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetMaxSpeed</span><span>（）；</span><span>//</span><span>既完成</span><span>ICar</span><span>的</span><span>GetMaxSpeed</span><span>（）接口方法又</span><span><span>&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; </span>//</span><span>完成</span><span>IBoat</span><span>的接口方法？显然不能够</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>};</span></p>
<p><strong><span>解决问题：</span></strong></p>
<p><strong><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></strong><span>显然上面这个尝试根本就无法成功，只用一个实现方法，怎么能够求出这个</span><span>ICarBoat</span><span>交通工具奔跑在马路上的最高时速，同时也能够求出航行在大海上的最大航行速度呢。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>上面这一问题矛盾就在一一个方法，却需要两个答案。看来</span><span>ICarBoat</span><span>要返回两个答案就必须有两个方法了，我们假设一个方法是求在陆地上奔跑的速度，名称为</span><span>GetCarMaxSpeed</span><span>（）；另一个方法是求在大海上航行的最大速度，名称为</span><span>GetBoatMaxSpeed</span><span>（）；那这两个方法又怎么和</span><span>GetMaxSpeed</span><span>（）接口方法联系起来呢；</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>幸运的是，我们找到了解决办法，而且解决办法有很多种，下面介绍一下继承法。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>class IXCar :public ICar</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span>&nbsp;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetMaxSpeed</span><span>（）</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>GetCarMaxSpeed();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetCarMaxSpeed</span><span>（）</span><span> = 0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span><span>；</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>class IXBoat:public IBoat</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetMaxSpeed</span><span>（）</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>GetBoatMaxSpeed();</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetBoatMaxSpeed</span><span>（）</span><span> = 0;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span><span>；</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>classCCarBoat: public IXCar , public IXBoat</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetCarMaxSpeed</span><span>（）</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&#8230; &#8230;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>virtual int GetBoatMaxSpeed</span><span>（）</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&#8230; &#8230;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>};</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<div align=center src_cetemp="/images/cppblog_com/andxie99/MultiInherit.JPG"><img src="http://www.cppblog.com/images/cppblog_com/andxie99/MultiInherit.JPG" border=0></div>
</span></span>
<p>&#160;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><strong><span><span>1.2.3<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span></strong><strong><span>this</span></strong><strong><span>跳转</span></strong></p>
<p><span>this</span><span>跳转是指的&#8220;对象同一性&#8221;问题。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>在单一继承的世界内，无论继承关系怎么复杂，针对于同一对象，无论它的子类或者父类的<span>this</span>指针永远相等。即如果</span><span><span> </span></span><span>B</span><span>从</span><span>A</span><span>继承，</span><span>那么 对于一个已经实例化<span>B</span>类的对象 <span>bObject</span>，永远有（<span>B*</span>）<span>&amp;bObject ==(A*)&amp;bObject </span>成立。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>但是在多继承的世界内，上面的等式就不能恒成立，对象的同一性受到了挑战。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>特别的是，在多继承世界内如果菱形关系存在情况下，如果对于已经实例化<span>B</span>类的对象<span>bObject; </span>（<span>Base*</span>）（<span>A1*</span>）<span>&amp;bObject != </span>（<span>Base*</span>）（<span>A2*</span>）<span>&amp;bObject </span>成立，当这种事情发生的时候我们就只能特殊处理了。这种情况在<span>COM</span>应用中处处都会发生。</span></p>
<p>&nbsp;</p>
<p><strong><span><span>1.3<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span></strong><strong><span>C++</span></strong><strong><span>多态的两种多态形式和区别</span></strong></p>
<p><strong><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span></strong><span>C++</span><span>有两种多态多态形式：</span></p>
<p><span><span>1、</span></span><span>编译时刻多态，编译时刻多态依靠函数重载或者模板实现</span></p>
<p><span><span>2、</span></span><span>运行时刻多态。运行时刻多态依靠需函数虚接口实现</span></p>
<img src ="http://www.cppblog.com/andxie99/aggbug/28494.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-07-21 16:18 <a href="http://www.cppblog.com/andxie99/archive/2007/07/21/28494.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++的底层机制</title><link>http://www.cppblog.com/andxie99/archive/2007/06/24/26855.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sun, 24 Jun 2007 12:43:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/24/26855.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/26855.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/24/26855.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/26855.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/26855.html</trackback:ping><description><![CDATA[<p>　　c++为我们所提供的各种存取控制仅仅是在编译阶段给我们的限制，也就是说是编译器确保了你在完成任务之前的正确行为，如果你的行为不正确，那么你休想构造出任何可执行程序来。</p>
<p>　　但如果真正到了产生可执行代码阶段，无论是c，c++,还是pascal，大家都一样，你认为c和c++编译器产生的机器代码会有所不同吗，你认为c++产生的机器代码会有访问限制吗？那么你错了。什么const，private，统统没有(const变量或许会放入只读数据段)，它不会再给你任何的限制，你可以利用一切内存修改工具或者是自己写一个程序对某一进程空间的某一变量进行修改，不管它在你的印象中是 private，还是public，对于此时的你来说都一样，想怎样便怎样。</p>
<p>　　另外，你也不要为c++所提供的什么晚期捆绑等机制大呼神奇，它也仅仅是在所产生的代码中多加了几条而已，它远没有你想象的那么智能，所有的工作都是编译器帮你完成，真正到了执行的时候，计算机会完全按照编译器产生的代码一丝不苟的执行。</p>
<p>　　(以下的反汇编代码均来自visial c++ 7.0)</p>
<p>　　一.让我们从变量开始-----并非你想象的那么简单</p>
<p>　　变量是什么，变量就是一个在程序执行过程中可以改变的量。换一个角度，变量是一块内存区域的名字，它就代表这块内存区域，当我们对变量进行修改的时候，会引起内存区域中内容的改变。但是你若是学习过汇编或是计算机组成原理，那么你就会清楚对于一块内存区域来说，根本就不存在什么名字，它所仅有的标志就是他的地址，因此我们若想修改一块内存区域的内容，只有知道他的地址方能实现。看来所谓的变量一说只不过是编译器给我们进行的一种抽象，让我们不必去了解更多的细节，降低我们的思维跨度而已。例如下面这条语句：</p>
<p>　　int a=10;</p>
<p>　　按照我们的思维习惯来讲，就是&#8220;存在一个变量a，它的值是10&#8221;，一切都显得那么的自然。我们不必去在乎什么所谓的地址以及其他的一些细节。然而在这条语句的底层实现中，a已经不能算是一个变量了，它仅仅是一个标记，代表一个地址的标记：</p>
<p>　　mov dword ptr[a],0Ah;</p>
<p>　　怎么样，这条语句不像上面那条易于接受吧，因为它需要了解更多的细节，你几乎不能得到编译器的任何帮助，一切思维上的跨越必须由你自己完成。这条语句应该解释为&#8220;把10写入以a为地址的内存区域&#8221;。你说什么？a有些像指针？对，的确像，但还不是，只不过他们的过程似乎是类似的。这里所说的跨越实际上就是从一个现实问题到具体地址以及内存区域的跨越。</p>
<p>　　二.引用：你可以拥有引用，但编译器仅拥有指针(地址)</p>
<p>　　看过了第一条，你一定对编译器的工作有了一定的了解，实际上编译器就是程序员与底层之间的一个转换层，它把一个高级语言代码转换为低级语言代码，一个编译器完成的转换跨度越大，那么它也就会越复杂，因为程序员的工作都由他代为完成了。C++编译器必然比汇编编译器复杂就是这个道理。如果我问你引用和指针是一样的吗？你或许会说当然不一样了，指针容易产生不安全的因素，引用却不会，真的不会吗？我们来看下面这段代码：</p>
<p>　　int *e=new int(10);</p>
<p>　　int &amp;f=*e;</p>
<p>　　delete e;</p>
<p>　　f=30;</p>
<p>　　你认为上面这段代码怎么样，我感觉就不很安全，它和指针有相同的隐患。因为它所引用的内存区域就不合法。</p>
<p>　　我个人认为，所谓的引用其实就是一种指针，只不过二者的接口并不相同，引用的接口有一定的限制。指针可以一对多，而引用却只能一对一，即&amp;refer不能被改变，但却并不能说一对一就是安全的，只不过危险的系数降低罢了。引用比指针更容易控制。</p>
<p>　　Ok, 下面来说说指针，曾经有过汇编经验的人一定会说，恩，指针的某些地方有些像汇编，尤其是那个&#8220;*&#8221;，怎么就那么像汇编中的&#8220;[]&#8221;啊。的确，它也涵盖了一个寻址的过程。看来指针的确是个比较低级的东西。然而引用却并不那么直接，虽然程序员用起来方便安全了许多。但是你要清楚，只有你可以拥有引用，编译器可没有这个工具，计算机并不认识这个东西。因此，它的底层机制实际上是和指针一样的。不要相信只有一块内存拷贝，不要认为引用可以为你节省一个指针的空间，因为这一切不会发生，编译器还是会把引用解释为指针。不管你相不相信，请看下面这段代码：</p>
<p>　　int&amp; b=a;</p>
<p>　　lea eax,[a];</p>
<p>　　mov dword ptr[b],eax;把a的地址赋给地址为b的一块内存</p>
<p>　　b=50;</p>
<p>　　mov eax,dword ptr[b];</p>
<p>　　mov dword ptr[eax],32h;</p>
<p>　　int *d=&amp;a;</p>
<p>　　lea eax,[a];</p>
<p>　　mov dword ptr[d],eax</p>
<p>　　*d=60;</p>
<p>　　mov eax,dword ptr[d]</p>
<p>　　mov dword ptr[eax],3ch;</p>
<p>　　以上的代码均来自具体的编译器，怎么样，相信了吧，好，让我再来做一个或许不怎么恰当的比拟，你一定编过有关线性表和栈的程序吧，线性表是一个非常灵活的数据结构，在他上面有许多的操作，然而栈呢，它是一个限制性操作的线性表，它的底层操作实际上是由线性表操作实现的。就好比stack与vector的关系，因此指针和引用的关系就好比线性表和栈的关系，引用也就是受限的指针，它对外的接口和指针虽然并不一样，但底层是相同的。</p>
<p>　　下面再来看看引用的一个重要用途，作为函数的参数传递的时候是怎样的情形：</p>
<p>　　void swapr(int &amp;a, int &amp;b)；</p>
<p>　　void swapr(int* a, int *b)；</p>
<p>　　int a=10;</p>
<p>　　int b=20;</p>
<p>　　swapr(a, b);</p>
<p>　　lea eax,[a];</p>
<p>　　push eax; //把a的地址压入堆栈</p>
<p>　　lea ecx,[b];</p>
<p>　　push ecx;</p>
<p>　　call swapr;</p>
<p>　　swapr(&amp;a, &amp;b);</p>
<p>　　lea eax,[a];</p>
<p>　　push eax;</p>
<p>　　lea ecx,[b];</p>
<p>　　push ecx;</p>
<p>　　call swapr;</p>
<p>　　怎么样，用引用和指针传递参数无论是在效率上还是在空间上都是完全一样的，如果妄想不传入地址就修改实参的值，简直就是天方夜谭，这就说明引用的本质就是指针。毕竟它们的行为都太相似了，如果不是这样，你还有什么方法去实现引用吗？记住，引用只不过是编译器为你提供的一个有用且安全的工具，对于机器代码可无法表示它，它把指针一对多的缺点去除，禁止了你的不安全的操作。但回到问题的本源，他们没有任何区别。 </p>
<img src ="http://www.cppblog.com/andxie99/aggbug/26855.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-24 20:43 <a href="http://www.cppblog.com/andxie99/archive/2007/06/24/26855.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>再读《背影》</title><link>http://www.cppblog.com/andxie99/archive/2007/06/23/26853.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 23 Jun 2007 02:12:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/23/26853.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/26853.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/23/26853.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/26853.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/26853.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 父亲早逝，今年已是第十个年头。上周末父亲节，思念之情无以言表，今天恰巧读到朱自清的《背影》，转载如下：<br><br>
<p align=center><strong><span>背影</span></strong><strong><span>&nbsp;</span></strong><strong><span>朱自清</span></strong><strong></strong></p>
<p><span>我与父亲不相见已二年余了，我最不能忘记的是他的背影。那年冬天，祖母死了，父亲的差使也交卸了，正是祸不单行的日子，我从北京到徐州，打算跟着父亲奔丧回家。到徐州见着父亲，看见满院狼藉的东西，又想起祖母，不禁簌簌地流下眼泪。父亲说，&#8220;事已如此，不必难过，好在天无绝人之路！&#8221;</span></p>
<p><span>回家变卖典质，父亲还了亏空；又借钱办了丧事。这些日子，家中光景很是惨淡，一半为了丧事，一半为了父亲赋闲。丧事完毕，父亲要到南京谋事，我也要回北京念书，我们便同行。</span></p>
<p><span>到南京时，有朋友约去游逛，勾留了一日；第二日上午便须渡江到浦口，下午上车北去。父亲因为事忙，本已说定不送我，叫旅馆里一个熟识的茶房陪我同去。他再三嘱咐茶房，甚是仔细。但他终于不放心，怕茶房不妥帖；颇踌躇了一会。其实我那年已二十岁，北京已来往过两三次，是没有甚么要紧的了。他踌躇了一会，终于决定还是自己送我去。我两三回劝他不必去；他只说，&#8220;不要紧，他们去不好！&#8221;</span></p>
<p><span>我们过了江，进了车站。我买票，他忙着照看行李。行李太多了，得向脚夫行些小费，才可过去。他便又忙着和他们讲价钱。<span>我那时真是聪明过分</span>，总觉他说话不大漂亮，非自己插嘴不可。但他终于讲定了价钱；就送我上车。他给我拣定了靠车门的一张椅子；我将他给我做的紫毛大衣铺好坐位。他嘱我路上小心，夜里警醒些，不要受凉。又嘱托茶房好好照应我。我心里暗笑他的迂；他们只认得钱，托他们直是白托！而且我这样大年纪的人，难道还不能料理自己么？<span>唉，我现在想想，那时真是太聪明了！</span></span></p>
<p><span>我说道，&#8220;爸爸，你走吧。&#8221;他望车外看了看，说，&#8220;我买几个橘子去。你就在此地，不要走动。&#8221;我看那边月台的栅栏外有几个卖东西的等着顾客。走到那边月台，须穿过铁道，须跳下去又爬上去。父亲是一个胖子，走过去自然要费事些。我本来要去的，他不肯，只好让他去。我看见他戴着黑布小帽，穿着黑布大马褂，深青布棉袍，蹒跚地走到铁道边，慢慢探身下去，尚不大难。可是他穿过铁道，要爬上那边月台，就不容易了。他用两手攀着上面，两脚再向上缩；他肥胖的身子向左微倾，显出努力的样子。这时我看见他的背影，我的泪很快地流下来了。我赶紧拭干了泪，怕他看见，也怕别人看见。我再向外看时，他已抱了朱红的橘子望回走了。过铁道时，他先将橘子散放在地上，自己慢慢爬下，再抱起橘子走。到这边时，我赶紧去搀他。他和我走到车上，将橘子一股脑儿放在我的皮大衣上。于是扑扑衣上的泥土，心里很轻松似的，过一会说，&#8220;我走了；到那边来信！&#8221;我望着他走出去。他走了几步，回过头看见我，说，&#8220;进去吧，里边没人。&#8221;<span>等他的背影混入来来往往的人里，再找不着了，我便进来坐下，我的眼泪又来了</span>。</span></p>
<p><span>近几年来，父亲和我都是东奔西走，家中光景是一日不如一日。他少年出外谋生，独力支持，做了许多大事。那知老境却如此颓唐！他触目伤怀，自然情不能自已。情郁于中，自然要发之于外；家庭琐屑便往往触他之怒。他待我渐渐不同往日。但最近两年的不见，他终于忘却我的不好，只是惦记着我，惦记着我的儿子。我北来后，他写了一信给我，信中说道，&#8220;我身体平安，惟膀子疼痛利害，举箸提笔，诸多不便，大约大去之期不远矣<span>。</span>&#8221;我读到此处，在晶莹的泪光中，看见那肥胖的，青布棉袍，黑布马褂的背影。唉！我不知何时再能与他相见！</span></p>
<p align=right><span>&nbsp;１９２５年１０月在北京。</span></p>
<img src ="http://www.cppblog.com/andxie99/aggbug/26853.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-23 10:12 <a href="http://www.cppblog.com/andxie99/archive/2007/06/23/26853.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>This case pointers cannot be used </title><link>http://www.cppblog.com/andxie99/archive/2007/06/16/26452.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 16 Jun 2007 12:45:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/16/26452.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/26452.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/16/26452.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/26452.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/26452.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; References allow the use of expressions involving the usual arithmetic operators for large objects without excessive copying. Pointers cannot be used because it is not possible to redefine the meaning of an operator applied to a pointer.</p>
<img src ="http://www.cppblog.com/andxie99/aggbug/26452.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-16 20:45 <a href="http://www.cppblog.com/andxie99/archive/2007/06/16/26452.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>2007最牛X网站收集</title><link>http://www.cppblog.com/andxie99/archive/2007/06/16/26433.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 16 Jun 2007 03:58:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/16/26433.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/26433.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/16/26433.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/26433.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/26433.html</trackback:ping><description><![CDATA[<p>50. 经典桌面</p>
<p>这个名叫东子的偏执狂不知花了多少工夫，mydeskcity.com的内容量达到了40G，很多图片都是站长本人在国外搜集后，自己进行加工的作品。<br><a href="http://www.mydeskcity.com/">http://www.mydeskcity.com/</a></p>
<p>49. 画猪头</p>
<p>在指定的对话框里面随便画一个猪头，然后点击"提交"，之后会得到一份关于你的个性的报告。当然大部分都是臭骂你的话，但是在你之前已经有965,541个人乐滋滋地找骂了&#8230;&#8230;<br><a href="http://drawapig.desktopcreatures.com/">http://drawapig.desktopcreatures.com/</a></p>
<p>48. 射精计算器</p>
<p>科学是严谨的，因此有人搞出了这么一个在线计算器：把你每周的次数和每次的大致距离填写进去，会得到你已经射了多少米、死了多少精虫的统计数据。<br><a href="http://strongbad.surrealistic.net/ejaculator.php">http://strongbad.surrealistic.net/ejaculator.php</a></p>
<p>47. 通缉犯</p>
<p>这里是全英国最危险的通缉犯发布榜，到目前为止还没见到一个女性（怎么搞的女同志们？撑起半边天来嘛！）你可以参照这里的照片躲开危险，也可以亲自去捉住在逃犯领取1万英镑的奖金。<br><a href="http://www.mostwanted-uk.org/">http://www.mostwanted-uk.org/</a></p>
<p>46. 粗口集合</p>
<p>为了表达对粗口和暴力精神的崇敬，对因殴打老婆而锒铛入狱的著名艺人Ross Kemp的欣赏和遗憾，他的Fans整了这么一个只有他的头像和他"名言"的网站，相当搞笑，堪称英文粗口经典集合。<br><a href="http://www.rosskemp.co.uk/">http://www.rosskemp.co.uk/</a></p>
<p>45. Google员工<br>中文拼音："妈妈说就算你注册的域名再长GOOGLE都能搜索出来" ,据说这是Google中国的员工注册的...打开看看,的确连到google了<br><a href="http://www.mamashuojiusuannizhucedeyumingzaichanggoogledounengsousuochulai.cn/">http://www.mamashuojiusuannizhucedeyumingzaichanggoogledounengsousuochulai.cn/</a></p>
<p>44. 百度员工</p>
<p>百度不服了...中文拼音："妈妈说就算你注册的域名再长baidu都能搜索出来" ...汗...你们在做什么...<br><a href="http://www.mamashuojiusuannizhucedeyumingzaichangbaidudounengsousuochulai.cn/">http://www.mamashuojiusuannizhucedeyumingzaichangbaidudounengsousuochulai.cn/</a></p>
<p>43. 读趣网<br>读趣网，收集了网友们最关心的好东西。Dotree.com，域名谐音,实在是不错。让人羡慕。<br><a href="http://www.dotree.com/">http://www.dotree.com</a></p>
<p>42. 超级装备</p>
<p>通过巨大的照片，了解当今最牛的跑车。<br><a href="http://www.topgear.com/">http://www.topgear.com/</a></p>
<p>41. 烂番茄</p>
<p>最近各种电影网站如同雨后春笋一般纷纷冒出头来，但是这个始终是最好的一个：这里评选出的是最烂的片子，并用"一般烂、很烂、超级烂"这样的级别给它们分类。参评作品中甚至还包括了一些电视游戏。<br><a href="http://www.rottentomatoes.com/">http://www.rottentomatoes.com/</a></p>
<p>40. 魔术吧</p>
<p>街头魔术联盟（Street Magic union），简称"SMU"。这里由一群魔术爱好者自发组织的团体。为所有热爱魔术的人们提供了窥探和偷技的阵地。<br><a href="http://www.magic8.cn/">http://www.magic8.cn/</a></p>
<p>39. 省钱网</p>
<p>天才的理财网，名气和好评迅速彪升，电视台专门为了它开了一档节目。在这里主持人Martin Lewis手把手教给你从租DVD到缴水费省钱的各种方法。<br><a href="http://www.moneysavingexpert.com/">http://www.moneysavingexpert.com/</a></p>
<p>38. 电影随便看</p>
<p>只要在这里下载一个免费软件，请你精于电脑的同事帮忙装好，全世界的电影就都成为你的囊中之物。无论它们是老片子还是现在正在播放的片子，记住手要快，因为很快会有人过来叫你把它们删掉。<br><a href="http://www.bittorrent.com/">http://www.bittorrent.com/</a></p>
<p>37. 免费电话</p>
<p>走到全世界的任何地方，都可以拨打免费的电话。对！一分钟也不用花，只要你装了Skype的这个软件，同时你也叫你的通话伙伴装上它。把耳麦和电脑接好，开始国际长途电话粥吧！<br><a href="http://www.skype.com/">http://www.skype.com/</a></p>
<p>36. 故事会</p>
<p>变态而又真实的各种故事－－如果不是版面限制，我们将很乐于把它们都登出来。比如"用头盔抵挡海鸥的进攻"、"护士偷看成人录像被开除"，只要是见到"Quirkies"的字样点进去就好。<br><a href="http://www.ananova.com/news">http://www.ananova.com/news</a></p>
<p>35. 坏女孩</p>
<p>海湾战争中，美国女兵Lynndie用手比划成枪的样子，指着伊拉克战犯的"那话儿"，这张照片成为人们永远不能忘记的一幕。这个网站也许是为了"纪念"她，搞了这个"模仿Lynndie"的活动，全世界的人都在作出那个姿势。<br><a href="http://www.badgas.co.uk/">http://www.badgas.co.uk/</a></p>
<p>34. 爆笑电视</p>
<p>如果你已经厌倦了现在的电视节目，不妨到这里下载每周一次Ricky的这档爆笑节目。每周一通过Rodcast开始播出一直持续周五。<br><a href="http://www.guardian.co.uk/rickygervais">http://www.guardian.co.uk/rickygervais</a></p>
<p>33. 肮脏美学</p>
<p>一个相当不错的KB网站，比起它来，大多数号称"天下第一KB网站"的网站都显得志大才疏。<br><a href="http://www.sickarts.com/">http://www.sickarts.com/</a></p>
<p>32. 内衣女人</p>
<p>Soho们的福音：这个内衣网站有着非常优秀的摄影、非常迷人的模特和非常性感的内衣，更重要的是你再也不用面红耳赤地去帮老婆买内衣了。<br><a href="http://www.agentprovocateur.com/">http://www.agentprovocateur.com/</a></p>
<p>31. md主机</p>
<p>什么?MD? -_-!!! 哪个国家的域名哦.(是一个空间提供商，有免费空间，还可以注册 xxx.host.md二级域名...)<br><a href="http://www.host.md/">http://www.host.md</a></p>
<p>30. Prank Mail</p>
<p>"想发匿名骚扰邮件吗？想让你的同事以为自己中了100万吗？"这真是一个邪恶的网站，可以提供各式各样的骚扰服务，好在，大多都是善意的。<br><a href="http://www.sharpmail.co.uk/">http://www.sharpmail.co.uk/</a></p>
<p>29. 交友</p>
<p>你是一个孤独的人？到这个只接受可信朋友注册的网站来看看（而不是随意上QQ上搜一个名为"小甜甜"的90多岁老奶奶）。顺便说一句，帕米拉&#183;安德森也是这里的会员。<br><a href="http://www.friendster.com/">http://www.friendster.com/</a></p>
<p>28. 微软？NO！火狐！</p>
<p>指向firefox,什么世道...<br><a href="http://www.ie7.com/">http://www.ie7.com/</a></p>
<p>27. 伤疤大赛</p>
<p>男人就喜欢显摆自己的伤疤，因此应该找个地方让他们比比看。在这里，有这种嗜好的人可以找到全世界的对手，不过别忘了，你"六岁时从火车上掉下来"留下的伤疤和这里的前十名相比看起来可能只是一个小针眼而已。<br><a href="http://www.scarmageddon.com/">http://www.scarmageddon.com/</a></p>
<p>26. 金色视频</p>
<p>就如同在你的电脑上开通了六万个电视频道一样，你只要点点鼠标就可以观看到各种电视节目，从体育到戏剧。这里有100万小时的剪辑供你免费观看。<br><a href="http://www.blinkx.tv/">http://www.blinkx.tv/</a></p>
<p>25. 疯狂的手指</p>
<p>一个极为简单但是极令人着迷的游戏，就是要看你能在多短时间内打完26个字母，然后把你的成绩转给同事们看，然后看着他们拼命敲键盘。我们的记录？6.4秒。但据说最高记录是在1.001秒内敲完了26个字母，是不是地球人啊，他！<br><a href="http://frenzy.morpheme.co.uk/frenzy/">http://frenzy.morpheme.co.uk/frenzy/</a></p>
<p>24. 眼睛的幻觉</p>
<p>德国某大学的科学家们贡献了这个神奇的眼睛魔术网站，在这里你可以体验"空间频率扭曲"，实际上那只是"你的眼睛背叛了你的心"而已。<br><a href="http://www.michaelbach.de/ot/index.html">http://www.michaelbach.de/ot/index.html</a></p>
<p>23. 全球富人榜</p>
<p>把你的收入水平打进去，看看你在地球的财富排行中数老几。你很有可能会惊奇地发现，确实你是属于高收入人群，同阿布在一起！<br><a href="http://www.globalrichlist.com/">http://www.globalrichlist.com/</a></p>
<p>22. 考拉宝</p>
<p>以为是考拉网的工具站，没想到是个人做的，不知道考拉网会怎么想。<br><a href="http://www.kaolaobao.cn/">http://www.kaolaobao.cn</a></p>
<p>21. 掘宝</p>
<p>据我们所知，掘宝网是世界上第一个严肃认真地购买线索资料进行宝藏发掘的网站。他们悬赏10万英镑寻找一个不知道被埋在什么地方的方盒子&#8230;&#8230;当然，这一切都是个游戏。<br><a href="http://www.perplexcity.com/">http://www.perplexcity.com/</a></p>
<p>20. 抓奖网</p>
<p>收集网上有奖活动的网站，见过的最专一的网站之一，倒是一个休闲的好去处<br><a href="http://www.zhuaj.com/">http://www.zhuaj.com</a></p>
<p>19. 可笑的脸</p>
<p>用吃奶的力气做个鬼脸，然后拍成照片传到网上。结果？结果你得到一个印着你的头像的杯子，而你的脸比杯子把儿弯曲得还厉害。<br><a href="http://www.shakeskin.com/">http://www.shakeskin.com/</a></p>
<p>18. 女尸解剖游戏</p>
<p>脱就一脱到底！可是，想想看，除去外套和蕾丝内衣之后，你还能继续脱掉这个女孩身上的什么吗？如果之前被告之是她的头发、面皮、骨头、肠子&#8230;&#8230;还敢将游戏进行到底吗？说实，变态和恶心的程度算不上高，但要把她身上的零件都拿光，还真够麻烦的。<br><a href="http://www.mmsjoy.com/flash/1180_1.htm">http://www.mmsjoy.com/flash/1180_1.htm</a></p>
<p>17. 跑光啦！</p>
<p>这个网站的引人之处就在于那些酒后出丑的姑娘们的照片。<br><a href="http://www.partyflashers.com/">http://www.partyflashers.com/</a></p>
<p>16. MP3问答</p>
<p>把你最喜欢的乐队名字写进去，然后玩一个10回合的小游戏，把正在播放的歌名正确猜对。<br><a href="http://www.scenta.co.uk/games/whats_that_song.cfm">http://www.scenta.co.uk/games/whats_that_song.cfm</a></p>
<p>15. 射门</p>
<p>一个与众不同的足球游戏：挑选你愿意参加的联赛和队伍，你在游戏中每进一球，都将给自己的联盟加上一分。<br><a href="http://www.playforyourclub.com/">http://www.playforyourclub.com/</a></p>
<p>14. 跳舞的傻瓜</p>
<p>我们猜测，叫每个打开此网页的人都哈哈大笑是站长的目的。上传或者选择一个头像，然后选择一个身体，再然后就让这个小兄弟在你的屏幕上不停地跳舞吧！<br><a href="http://www.muglets.com/">http://www.muglets.com/</a></p>
<p>13. 养盒子</p>
<p>这个游戏有一点点抽象，但是却很好玩：按照符合逻辑的顺序，用不同的道具来建设这个盒子，顺序正确它就会逐步长成为&#8230;&#8230;不知道什么东西，我们的逻辑思维还没那么好。<br><a href="http://www.eyemaze.com/grow/cube/">http://www.eyemaze.com/grow/cube/</a></p>
<p>12. 淘宝贝</p>
<p>在一些男性会为之发疯的好玩具、小物件儿出现在商店里之前，它们极有可能会出现在这里。这里的东西有"第一人称射击单车控制器"还有能够把你的PC、PS2和XBOX连到一起的连接装置&#8230;&#8230;欢迎来到天堂！<br><a href="http://www.engadget.com/">http://www.engadget.com/</a></p>
<p>11. 扑克先生</p>
<p>管理员最热爱的体育项目之一就是扑克牌，因此我们正好知道一个不错的扑克网站。你每天都可以坐在自己的办公桌后面于7万名其他的扑克爱好者们在线拼杀&#8230;&#8230;<br><a href="http://www.partypoker.com/">http://www.partypoker.com/</a></p>
<p>10. 偷拍地球</p>
<p>从一个悬挂在太空、注视着地球的卫星的角度开始，一点点放大，一直看到大北窑的堵车状&#8230;&#8230;有点变态，不过很好玩。有个问题：如果我们都能看到这么多，那么军队的电脑上都能看到什么呢？<br><a href="http://www.flashearth.com/">http://www.flashearth.com/</a></p>
<p>9. 电台天堂</p>
<p>建立你自己的私人电台名称（例如"老陈FM"），输入你喜欢的波段地址，然后就等着从电脑里飘来美妙MP3吧！就像你从Amazon里面购买来的一样！<br><a href="http://www.pandora.com/">http://www.pandora.com/</a></p>
<p>8. 个人空间</p>
<p>有个美国佬最近把50多亿美金都仍在一个网站上，由此我们可以预见到互联网的未来。赶紧找个空间创建你自己的天地，把你的照片、音乐传上去，再搞点小买卖。这里已经有4000万用户，数目相当于丹麦、瑞典、澳大利亚和瑞士的人口总和。<br><a href="http://www.myspace.com/">http://www.myspace.com/</a></p>
<p>7. 飞虎队</p>
<p>网站首页上写着：这里的主要内容是介绍香港pol.ice的特种部队－－"特别任务连"。特务连？不，是飞虎队。虽然站长声称这不是官方网站，但里面大量装备足以让我们飙出鼻血。<br><a href="http://www.sdupro.com/index2.html">http://www.sdupro.com/index2.html</a></p>
<p>6. 照片分享</p>
<p>现在连照片的上传和分享都有软件可以帮你打理完成了：下载这个免费的软件，然后往里面填好你的链接地址，就可以和朋友们分享了。如果你乐意，你甚至可以把它们变成海报、画册、甚至是邮票，当然也可以自由浏览他人的作品。<br><a href="http://www.flickr.com/">http://www.flickr.com/</a></p>
<p>5. 安全隐私</p>
<p>任何人都可以登录这个网站，邮寄一张电子贺卡，吐露心底的秘密或者偷窥别人的秘密。浏览者可以挖掘出人们最悲惨、最滑稽、最古怪、最疯狂的一面。更重要的是这里的秘密最安全。<br><a href="http://postsecret.blogspot.com/">http://postsecret.blogspot.com/</a></p>
<p>4. 秘密的Google</p>
<p>我们没疯：你一直点击"更多"，直到它最终带领你进入一个全新的Google世界。你直到通过Google你可以用一颗卫星看到自己家的房子吗？用6GOOG得到免费的地图、电影放映时间？把"鱼"这个词翻译成意大利语？你不知道，那就来试试吧！<br><a href="http://www.google.com/">http://www.google.com/</a></p>
<p>3. 网络精选</p>
<p>住在伦敦的网络老油条理查德创建了这个网站，上面包含网络上最好的视频剪辑、游戏、姑娘和图片。"我本来的动机是要把邮箱里面每天收到的各种好玩儿的东西集中起来放到网上和朋友们分享。"他说。你在这里泡上整整一个下午，也不一定能真正看完这儿全部宝贝的九牛一毛。<br><a href="http://www.kontraband.com/">http://www.kontraband.com/</a></p>
<p>2. 60X1</p>
<p>被网名传为世界最牛&#215;的网站，它的域名由60个1组成。在首页有一个小小的"ENTER"健，点进去是一幅又一幅漫画，创意一流，无懈可击。我们猜测，这也许是个伊拉克人的作品吧&#8230;&#8230;<br><a href="http://www.111111111111111111111/">http://www.111111111111111111111</a> ... 111111111111111.com (自己输入试试吧)</p>
<p>1. 冠军</p>
<p>我们粗略计算了一下在公司玩那种网上下载的小游戏的时间，结果可以用年来计算。这里的东西就是专门给我们这样喜欢浪费时间的人准备的，无论是第一人称射击游戏还是赛车游戏，基本上全都是免费的。例如"武装直升机3"和"愤怒机甲"，它们就是两个画面十分漂 亮的爽游戏，快和你的职业前途说"再见"吧！<br><a href="http://www.miniclip.com/">http://www.miniclip.com/</a></p>
<p>0. bolm<br>最不牛X的：<a href="http://bolm.cn/">http://bolm.cn</a>&nbsp; --&nbsp; 必看</p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/andxie99/aggbug/26433.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-16 11:58 <a href="http://www.cppblog.com/andxie99/archive/2007/06/16/26433.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>被误解的C++</title><link>http://www.cppblog.com/andxie99/archive/2007/06/15/26396.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Fri, 15 Jun 2007 12:41:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/15/26396.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/26396.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/15/26396.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/26396.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/26396.html</trackback:ping><description><![CDATA[<p><br>&nbsp;&nbsp;&nbsp; 从CSDN上读到一篇文章，深有同感，原文如下：<br>&nbsp;&nbsp;&nbsp; 传统上认为，C++相对于目前一些新潮的语言，如Java、C#，优势在于程序的运行性能。这种观念并不完全。如果一个人深信这一点，那么说明他并没有充分了解和理解C++和那个某某语言。同时，持有这种观念的人，通常也是受到了某种误导（罪魁祸首当然就是那些财大气粗的公司）。对于这些公司而言，他们隐藏了C++同某某语言间的核心差别，而把现在多数程序员不太关心的差别，也就是性能，加以强化。因为随着cpu性能的快速提升，性能问题已不为人们所关心。这叫&#8220;李代桃僵&#8221;。很多涉世不深的程序员，也就相信了他们。于是，大公司们的阴谋也就得逞了。<br>&nbsp;&nbsp;&nbsp; 这个文章系列里，我将竭尽所能，利用一些现实的案例，来戳破这种谎言，还世道一个清白。但愿我的努力不会白费。</p>
<p><br>软件工程</p>
<p>&nbsp;&nbsp;&nbsp; 一般认为，使用Java或C#的开发成本比C++低。但是，如果你能够充分分析C++和这些语言的差别，会发现这句话的成立是有条件的。这个条件就是：软件规模和复杂度都比较小。如果不超过3万行有效代码（不包括生成器产生的代码），这句话基本上还能成立。否则，随着代码量和复杂度的增加，C++的优势将会越来越明显。<br>&nbsp;&nbsp;&nbsp; 造成这种差别的就是C++的软件工程性。在Java和C#大谈软件工程的时候，C++实际上已经悄悄地将软件工程性提升到一个前所未有的高度。这一点被多数人忽视，并且被大公司竭力掩盖。<br>&nbsp;&nbsp;&nbsp; 语言在软件工程上的好坏，依赖于语言的抽象能力。从面向过程到面向对象，语言的抽象能力有了一个质的飞跃。但在实践中，人们发现面向对象无法解决所有软件工程中的问题。于是，精英们逐步引入、并拓展泛型编程，解决更高层次的软件工程问题。（实际上，面向对象和泛型编程的起源都可以追溯到1967年，但由于泛型编程更抽象，所以应用远远落后于面向对象）。<br>&nbsp;&nbsp;&nbsp; 一个偶然的机会，我突发奇想，试图将货币强类型化，使得货币类型可以采用普通的算术表达式计算，而无需关心汇率换算的问题。具体的内容我已经写成文章，放在blog里：<a href="http://blog.csdn.net/longshanks/archive/2007/05/30/1631391.aspx">http://blog.csdn.net/longshanks/archive/2007/05/30/1631391.aspx</a>。（CSDN的论坛似乎对大文章有些消化不良）。下面我只是简单地描述一下问题，重点还在探讨语言能力间的差异。<br>&nbsp;&nbsp;&nbsp; 当时我面临的问题是：假设有四种货币：RMB、USD、UKP、JPD。我希望能够这样计算他们：<br>RMB rmb_(1000);<br>USD usd_;<br>UKP ukp_;<br>JPD jpd_(2000);</p>
<p>usd_=rmb_;//赋值操作，隐含了汇率转换。usd_实际值应该是1000/7.68=130.21<br>rmb_=rmb_*2.5;//单价乘上数量。<br>ukp_=usd_*3.7;//单价乘上数量，赋值给英镑。隐含汇率转换。<br>double n=jpd_/(usd_-ukp_);//利用差价计算数量。三种货币参与，隐含汇率转换。<br>而传统上，我们通常用一个double或者currency类型表示所有货币。于是，当不同币种参与运算时，必须进行显式的汇率转换：<br>double rmb_(100), usd_(0), ukp_(0), jpn_(2000);</p>
<p>usd_=rmb_*usd_rmb_rate;<br>ukp_=(usd_*usd_ukp_rate)*3.7;<br>double n=jpd_/((usd_*usd_jpd_rate)-(ukp_*ukp_jpd_rate))<br>很显然，强类型化后，代码简洁的多。并且可以利用重载或特化，直接给出与货币相关的辅助信息，如货币符号等（这点我没有做，但加上也不复杂）。<br>在C++中，我利用模板、操作符重载，以及操作符函数模板等技术，很快开发出这个货币体系：<br>template&lt;int CurrType&gt;<br>class Currency<br>{<br>public:<br>&nbsp;&nbsp; Currency&lt;CurrType&gt;&amp; operator=(count Currency&lt;ct2&gt;&amp; v) {<br>&#8230;<br>&nbsp;&nbsp; }<br>public:<br>&nbsp;&nbsp; double _val;<br>&#8230;<br>};<br>template&lt;int ty, int tp&gt;<br>inline bool operator==(currency&lt;ty&gt;&amp; c1, const currency&lt;tp&gt;&amp; c2) {<br>&#8230;<br>}<br>&nbsp;<br>template&lt;int ty, int tp&gt;<br>inline currency&lt;ty&gt;&amp; operator+=(currency&lt;ty&gt;&amp; c1, const currency&lt;tp&gt;&amp; c2) {<br>&#8230;<br>}<br>template&lt;int ty, int tp&gt;<br>inline currency&lt;ty&gt; operator+(currency&lt;ty&gt;&amp; c1, const currency&lt;tp&gt;&amp; c2) {<br>&#8230;<br>}<br>&#8230;<br>总共不超过200行代码。（当然，一个工业强度的货币体系，需要更多的辅助类、函数等等。但基本上不会超过500行代码）。如果我需要一种货币，就先为其指定一个int类型的常量值，然后typedef一下即可：<br>const int CT_RMB=0;//也可以用enum<br>typedef Currency&lt;CT_RMB&gt;RMB;<br>const int CT_USD=1;<br>typedef Currency&lt;CT_USD&gt;USD;<br>const int CT_UKP=2;<br>typedef Currency&lt;CT_USD&gt;USD;<br>const int CT_JPD=3;<br>typedef Currency&lt;CT_USD&gt;USD;<br>&#8230;<br>每新增一种货币，只需定义一个值，然后typedef即可。而对于核心的Currency&lt;&gt;和操作符重载，无需做丁点改动。<br>之后，我试图将这个货币体系的代码移植到C#中去。根据试验的结果，我也写了一篇文章（也放在blog里：<a href="http://blog.csdn.net/longshanks/archive/2007/05/30/1631476.aspx">http://blog.csdn.net/longshanks/archive/2007/05/30/1631476.aspx</a>）。我和一个同事（他是使用C#开发的，对其更熟悉），用了大半个上午，终于完成了这项工作。<br>令人丧气的事，上来就碰了个钉子：C#不支持=的重载。于是只能用asign&lt;&gt;()泛型函数代替。之后，由于C#的泛型不支持非类型泛型参数，即上面C++代码中的int CurrType模板参数的泛型对等物，以及C#不支持泛型操作符重载，整个货币系统从泛型编程模式退化成了面向对象模式。当然，在我们坚持不懈的努力下，最后终于实现了和C++中一样的代码效果（除了那个赋值操作）：<br>assign(rmb_, ukp_);<br>assign(usd_, rmb_*3.7);<br>&#8230;<br>我知道，有些人会说，既然OOP可以做到，何必用GP呢？GP太复杂了。这里，我已经为这些人准备了一组统计数据：在C#代码中，我实现了3个货币，结果定义了4个类（一个基类，三个货币类）；重载30个算术操作符（和C++一样，实现10个操作符，每个类都得把10个操作符重载一遍）；6个类型转换操作符（从两种货币类到第三货币类的转换操作符）。<br>这还不是最糟的。当我增加一个货币，货币数变成4个后，数据变成了：5个类；40个算术操作符重载；12个类型转换操作符重载。<br>当货币数增加到10个后：11个类；100个算术操作符重载；90个类型转换操作符重载。<br>反观C++的实现，3个货币时：1个类模板；1个赋值操作符重载模板；10个算术操作符重载模板；外加3个const int定义，3个typedef。<br>10个货币时：1个类模板；1个赋值操作符重载模板；10个算术操作符重载模板；const int定义和typedef分别增加到10个。<br>也就是说C++版本的代码随着货币的增加，仅线性增加。而且代码行增加的系数仅是2。请注意，是代码行！不是类、函数，也不是操作符的数量。而C#版本的代码量则会以几何级数增加。几何级数！！！<br>这些数字的含义，我就不用多说了吧。无论是代码的数量、可维护性、可扩展性C++都远远好于C#版本。更不用说可用性了（那个assign函数用起来有多难看）。<br>&nbsp;&nbsp;&nbsp; 我知道，有些人还会说：货币太特殊了，在实践中这种情况毕竟少见。没错，货币是比较特殊，但是并没有特殊到独此一家的程度。我曾经做了一个读取脚本中的图形信息，并绘图输出的简单案例，以展示OOP的一些基本概念，用于培训。但如果将其细化，可以开发出一个很不错的脚本绘图引擎。其中，我使用了组合递归、多态和动态链接，以及类工厂等技术。就是那个类工厂，由于我使用了模板，使得类工厂部分的代码减少了2/3，而且没有重复代码，更易维护。关于抽象类工厂的GP优化，Alexandrescu在其《Modren C++ design》中，有更多的案例。同样的技术，还可以推广到业务模型的类系统中，优化类工厂的代码。<br>如果还不满意，那么就去看看boost。boost的很多库实现了几乎不可想象的功能，比如lambda表达式、BGL的命名参数等等。它为我们很多优化软件代码新思路，很多技术和方法可以促进我们大幅优化代码，降低开发成本。<br>&nbsp;&nbsp;&nbsp; 最后，如果你认为C#的最大的优势在于.net平台，那我可以告诉你，这个世界上还有一种东西叫C++/CLI，完全可以满足.net的开发，而且更好，足以擦干净.net那肮脏的屁股。不过，这将会是另外一个故事了&#8230;<br></p>
<img src ="http://www.cppblog.com/andxie99/aggbug/26396.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-15 20:41 <a href="http://www.cppblog.com/andxie99/archive/2007/06/15/26396.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于系统进程的一点很基础的知识</title><link>http://www.cppblog.com/andxie99/archive/2007/06/09/25900.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 09 Jun 2007 07:36:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/09/25900.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/25900.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/09/25900.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/25900.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/25900.html</trackback:ping><description><![CDATA[<br>&nbsp;&nbsp;&nbsp; 系统进程<br>&nbsp;&nbsp;&nbsp; Windows NT/2000操作系统拥有少量的系统进程来管理登录、服务、用户进程。你能通过任务管理器列出系统进程或者通过Platform SDK的任务列表工具（tlist）来找到他们。<br>&nbsp;&nbsp;&nbsp; 当Windows NT/2000操作系统运行时，可以将进程大致分成三个层次：<br>&nbsp;&nbsp;&nbsp; 第一层就包含一个系统进程——系统闲逛进程，该进程的ID为0；<br>&nbsp;&nbsp;&nbsp; 第二层包含所有其他系统进程，这些进程开始于一个称为system的进程，该进程是session manager process(smss.exe)的父进程，session manager process 是Win32 subsystem process(csrss.exe)和logon process(winlogon.exe)的父进程；<br>&nbsp;&nbsp;&nbsp; 第三层开始于一个程序管理进程（explorer.exe），它是所有用户进程的父进程。
<img src ="http://www.cppblog.com/andxie99/aggbug/25900.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-09 15:36 <a href="http://www.cppblog.com/andxie99/archive/2007/06/09/25900.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一道面试题</title><link>http://www.cppblog.com/andxie99/archive/2007/06/03/25393.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sun, 03 Jun 2007 10:27:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/03/25393.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/25393.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/03/25393.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/25393.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/25393.html</trackback:ping><description><![CDATA[<br>&nbsp;&nbsp;&nbsp; 这道题不是很难，但面试的时候一定要冷静，其实很多事情只要找到突破口，问题就迎刃而解了。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A B C D E<br>&nbsp;&nbsp;&nbsp; &#215;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4<br>&nbsp;&nbsp;&nbsp; --------------------<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;E D&nbsp;C&nbsp;B A<br>&nbsp;&nbsp;&nbsp; A、B、C、D、E分别代表一位不同的数字，求 A、B、C、D、E。 
<img src ="http://www.cppblog.com/andxie99/aggbug/25393.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-03 18:27 <a href="http://www.cppblog.com/andxie99/archive/2007/06/03/25393.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个简单的不依靠MFC的面向对象的Windows程序</title><link>http://www.cppblog.com/andxie99/archive/2007/06/02/25315.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 02 Jun 2007 04:36:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/06/02/25315.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/25315.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/06/02/25315.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/25315.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/25315.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp; 闲时顺手翻了翻《Windows Graphics Programming》，发现里面的示例代码很不错，对设计应用程序框架和理解现有的应用程序框架很有帮助（尤其是MFC）。先来看一个很简单的用面向对象的思想包装API函数的KWindow类。示例代码贴出来，申明一下，代码不是我写的，但有可能做一些改动，加了很多罗嗦的注释，只是想节约以后阅读的时间。&nbsp;&n...&nbsp;&nbsp;<a href='http://www.cppblog.com/andxie99/archive/2007/06/02/25315.html'>阅读全文</a><img src ="http://www.cppblog.com/andxie99/aggbug/25315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-06-02 12:36 <a href="http://www.cppblog.com/andxie99/archive/2007/06/02/25315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>程序员创业</title><link>http://www.cppblog.com/andxie99/archive/2007/05/04/23419.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Fri, 04 May 2007 14:43:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/05/04/23419.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/23419.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/05/04/23419.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/23419.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/23419.html</trackback:ping><description><![CDATA[<p><br>&nbsp;&nbsp;&nbsp; 当人们还在浩叹第一次网络泡沫破灭的时候，互联网已经悄悄迎来了它的第二个春天；从某种意义上看，甚至已经进入了夏天——热烈但不乏浮躁、兴奋但失之肤浅。某位投资人声称今年总共有三十亿美金资本进入中国，言下之意，大家都可以甩开膀子大干快上，登陆纳市不好说，搞笔钱进来花差花差多半是没问题的。</p>
<p>&nbsp;&nbsp;&nbsp; 另一方面，程序员创业，在中国乃至国外，都不是什么新鲜事儿。我们是那么一群聪明、优秀的家伙，大脑发达，点子就像啤酒的泡沫，扑腾扑腾直往外冒，天生我才，有什么做不到的呢？遥想比尔盖茨当年，西装革履，谈笑间，多少豪杰灰飞烟灭&#8230;&#8230;</p>
<p>&nbsp;&nbsp;&nbsp; 于是我看到，无数公司成立了，眼看他雄心勃勃，眼看他一败涂地。成败固然不足以论英雄，然而英雄却不得不面对可能的成败。可惜的是，程序员朋友们在创业的时候，往往没有做好充分准备。据一些资料显示，百分之七十五的新创公司，会在两、三年内倒闭。笔者也曾经见过许多程序员创业失败的个案；成功或不成功，有很多因素制约；对于立志创业的程序员，至少应该突破三关。</p>
<p>&nbsp;&nbsp;&nbsp; 第一是模式关。你的创业计划，也许起源于灵机一动。可惜的是，好点子并不能保证你创业成功。我相信多数程序员的点子，尚不至于低级到靠软色情、盗版、恶性SEO等等下作手段去骗取广告费的地步，但怎么从点子变成盈利模式，却是让很多创业者迷惑的事情。在一些业界聚会上，总听到类似&#8220;只要有流量，总有办法赚钱&#8221;之类的说法，在2000年持同样言论的创业者，多数已经成为失败的先烈，因为他们始终没明白，赚现钱的生意才是好生意。三大门户成功的要点，在于他们想出办法，把流量转化为盈利模式。缺乏有效的模式，流量只是成本。确定有效经营模式、组建有力创业团队，是首要任务。</p>
<p>&nbsp;&nbsp;&nbsp; 第二是管理关。从程序员变成管理者，是艰难的过程。你得明白两件事：一、管理和写程序一样，是门科学；二、人和计算机不一样，人有感情、会出错。协调沟通能力，是程序员创业必备的素质。曾经眼见一些项目经理，和手下技术人员通过邮件争辩不休，甚至发展到在Blog上互相嘲讽，这样的管理，可谓彻底失败。另一个极端是，和手下称兄道弟、一团和气，工作被感情所左右，酒肉害了朋友。管理有那么难吗？我看未必。只做对公司有利的事，就是根本原则。在和你的手下打交道时，请三思：我这么做，对公司有好处吗？对事业有好处吗？如果答案是否定的，那你需要另一个解决方案。</p>
<p>&nbsp;&nbsp;&nbsp; 第三是坚持关。一位多次创业不成功的朋友告诉我，他总结了一条&#8220;三年定律&#8221;，即任何事如果不能坚持三年，则一定失败。诚哉斯言！另一位朋友说，中国人相信机会，西方人相信方向和时间，虽有些偏激，却也不乏道理。许多程序员都属于思维活跃、点子特多的一类人，当有新鲜的想法出来时，他们倾向于放弃或冷落手上正在执行的计划。点子复点子，点子何其多，每天新点子，万事成蹉跎。西谚有云，双鸟在林不如一鸟在手；吃到嘴里的鸭子才是好鸭子，湖里那只鸭子看起来比较肥？也许吧，不过，吃了这只鸭子再去涉水抓那只，是不是更有把握呢？</p>
<p>&nbsp;&nbsp;&nbsp; 文短意深，未尽之处不及一一道来。奉上忠言数句，与程序员朋友们共勉：你永远不是最聪明的人；手下比你强是好事；创业不怕起步晚，只怕起个不停。<br>&nbsp;<br><br>&nbsp;原文地址：<a href="http://blog.csdn.net/ljah/archive/2007/05/04/1596366.aspx">http://blog.csdn.net/ljah/archive/2007/05/04/1596366.aspx</a></p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/andxie99/aggbug/23419.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-05-04 22:43 <a href="http://www.cppblog.com/andxie99/archive/2007/05/04/23419.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么是高级C++？</title><link>http://www.cppblog.com/andxie99/archive/2007/04/22/22600.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sun, 22 Apr 2007 11:50:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/04/22/22600.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/22600.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/04/22/22600.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/22600.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/22600.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; 整理资料时，发现了《什么是高级C++》这个ppt。这是一个C++发展方向的介绍，个人觉得很不错，把内容贴了出来，同是也可以<a href="http://www.cppblog.com/Files/andxie99/《什么是高级C++》.rar">点击下载</a>。<br><br></p>
<p align=center><strong>什么是高级C++？</strong></p>
<p align=center>——软件工业化时代的C++价值观<br>孟岩<br>《程序员》杂志社</p>
<p><br><strong>开门见山</strong></p>
<p>主要论点：<br>&nbsp;&nbsp;&nbsp; 1. C++本质上是一种重&#8220;创新&#8221;而轻&#8220;生产&#8221;的语言，到目前为止仍然是主流语言中最适合技术创新的一个；<br>&nbsp;&nbsp;&nbsp; 2. 1995年之前，整个软件产业处于&#8220;创新为王&#8221;的阶段，C++是最适合这个阶段的语言，这是C++红极一时的大背景和根本原因。<br>&nbsp;&nbsp;&nbsp; 3. 1995年发生了一系列影响深远的事件，软件产业整体上转向工业化，为了支持工业化，创新的重点由技术创新转向体系创新。然而C++没有能够迅速适应这一变化。<br>&nbsp;&nbsp;&nbsp; 4. 今天，C++应当准确定位，弥补不足，有针对性地发展，它将仍然是最重要的几种工业级语言之一。</p>
<p><br><strong>从一本书说起</strong><br>James Coplien，Advanced C++ Programming Styles and Idioms, Addison Wesley, 1991<br>—— 市面上唯一一本名副其实的&#8220;高级&#8221;C++书（Scott Meyers）<br>&nbsp;●面向对象特性的运用和把握<br>&nbsp;●面向对象的程序风格<br>&nbsp;●动态特征的运用和超越<br>&nbsp;●符号语言模拟<br>&nbsp;●设计模式</p>
<p>&nbsp;&nbsp;&nbsp; 这本书代表了当时专家们对于&#8220;高级C++&#8221;的理解，换句话说代表了当时C++社群的一个审美价值取向。我们看到了什么？技术、技巧、风格、模式，但没有与工程相关的东西。更有意思的事情是，这本书的中文版12年后被剽窃出版，此时书中对于C++面向对象能力发挥到了我当时没有想到的程度。这说明即使在template被广泛应用之前，C++语言的技巧性就达到了如此的高度。然而耐人寻味的是，书中最高深的技巧从来就没有在C++实践中流行过。</p>
<p><strong>另一本书...</strong><br>Scott Meyers, Effective C++ ，1991年第1版，1998年第二版，2005年第三版。<br>&nbsp;●来自教学经验<br>&nbsp;●最初想开发一个代码扫描工具<br>&nbsp;●包含实际工程建议<br>&nbsp;●历史上最重要的C++著作之一</p>
<p>&nbsp;&nbsp;&nbsp; 这本书出版的同时，还有一本在C++历史上影响更大的书问世——Scott Meyers的Effective C++。这本书并没有过多地探索语言技巧，而是探讨实践中应当遵循的规则，或者换句话说，探讨怎样在应用这种语言的同时保持软件的质量，提高开发效率。这本书的内容被整个C++社群熟知并吸收，至今仍在翻新，影响着更多的人。</p>
<p><strong>还是在1991年...</strong><br>&nbsp;●&#8220;按照1991年3月C++程序员增长的速度计算，到1996年5月，全世界每一个人都将成为C++程序员。此后我们将不得不教外星人学习C++。&#8221;<br>&nbsp;●问题：当时人们为什么如此疯狂地学习一种新语言？<br>&nbsp;&nbsp;&nbsp; 答案很有趣：大部分人是盲从。但他们所追随的人并非等闲之辈，几乎所有在AT&amp;T Bell Labs、Sun、Borland、IBM、Microsoft的C语言大师都转向C++（Brain Kernighan，Jon Bentley，Peter van der Linden）。而这些人转向C++，不是因为他们知道Effective C++，而是因为他们知道Advanced C++。什么意思呢？就是说人们转向C++，是因为C++充满了令人兴奋的新技巧和未知的创新空间。<br></p>
<p><br><strong>1991年...</strong><br>&nbsp;●5000行C代码可以写一个完整的应用程序，获得数万$的回报；<br>&nbsp;●一个TSR式的Help程序可以以shareware的方式通过磁盘发行，开发者银行户头里会收到大量汇款；<br>&nbsp;●John Carmark和Michael Abrash正在各自擅长的方向上不断创新。Doom发行后，id获得收入一度超过微软销售额。</p>
<p><strong>C++历史选择中&#8220;创新&#8221;压倒&#8220;生产&#8221;</strong><br>&#8220;相信程序员&#8221;；<br>Be an enable language;<br>Zero overhead；<br>STL投票的通过；<br>偏特化的引入<br>多继承<br>Generic/Generated/Meta<br>IOStream库的设计<br>Loki/Boost<br><br><span style="COLOR: red">counted_ptr被否决<br>可选GC方案被否决<br>加入类似delegate的对象方法指针提议未引起关注；<br>virtual关键字<br>exception机制<br>缺乏Thread, Network, Regex, DB...等标准库<br>没有ABI规范<br>孱弱的RTTI</span></p>
<p>&nbsp;&nbsp;&nbsp; 并不是事后诸葛亮式的谴责，这就是C++的历史选择，无所谓对错。</p>
<p>&nbsp;&nbsp;&nbsp; C++重创新轻生产，重技巧轻规范，语言上的创新试验直到1996年ANSI C++标准草案落地才结束。直到2001年Modern C++ Design出版，人们还不断地发现新的语言运用技巧。我们每个人都经历过这个阶段，在实践中发现一个问题，想方设法用尽各种语言技巧来克服它，成则欣喜，败不气馁。我们都曾经相信，C++中一切问题都可以优雅地解决，只有想不到，没有做不到。问题是，从Advanced C++到Modern C++ Design，许许多多令人第一眼看上去无比惊喜的技术，最后在实践中被大范围推广运用的少之又少。C++大师们说这是教育问题，真的是这样吗？</p>
<p><strong>C++社群的价值观</strong><br>&nbsp;●用优雅的技巧解决复杂问题<br>&nbsp;●自己动手，丰衣足食<br>&nbsp;●决不让运行时效率蒙受半点损失<br>&nbsp;●妙者为王<br>&nbsp;&nbsp;&nbsp; &#8220;管理一群C++程序员就像放牧一群骄傲的猫。&#8221;——B. Moo<br>&nbsp;&nbsp;&nbsp; &#8220;C++程序员是高速公路上穿着短皮茄克，带着墨镜，抽着雪茄，挥舞着铁链的英勇无畏的摩托骑士。&#8221; ——VC产品经理</p>
<p><strong>1995年：转折点<br></strong>&nbsp;●Windows 95问世：GUI时代、保护模式操作系统时代、多线程时代的到来，是推动软硬件规模迅速膨胀；<br>&nbsp;●Netscape Navigator vs. Internet Explorer: Web的兴起将人类一下子拖入互联网时代, 个人与企业应用软件网络化；<br>&nbsp;●Java诞生：提供了网络时代、跨平台时代优于C++的企业应用软件开发语言；<br>&nbsp;●COM时代到来<br>&nbsp;●Delphi诞生：创新与工程原则平衡的典范；</p>
<p><br><strong>1995年：C++全盛时代</strong><br>&nbsp;●C++标准草案接近完成，语言基本稳定；<br>&nbsp;●C++工具大战结束：来自商业竞争的动力消失，MFC获胜；<br>&nbsp;●很多主流软件厂商转向C++，C++开始在大范围内被用于大规模软件开发；<br>&nbsp;●一切迹象表明，软件产业的重点将有创新转向生产。但是：C++社群在指导思想上并没有发生相应的变化。</p>
<p>&nbsp;<br><strong>我们的历史失误</strong><br>&nbsp;●C++社群从来没有联合起来支持任何一个跨平台的二进制组件标准（如COM/SOM/CCM）和基础库（如Apache APR、ACE OS Wrapper）；<br>&nbsp;●C++社群从来没有联合起来支持任何一个跨平台的C++虚拟机、解释器、内存检测工具和错误录像工具，也从来没有促成过一个安全的库；<br>&nbsp;●Boost出现于1999-2000年，而在此之前的跨平台C++库都没有获得广泛的支持；<br>&nbsp;●钟情于用C++语法（无论多么复杂和稀奇古怪）完成所有的任务，却丢掉了老祖宗C语言的看家法宝——Little Language；<br>&nbsp;●对于风格争论不休，对于明显的技术进步拒不接受，对于很多后来被证明并不实用的技巧趋之若鹜。</p>
<p>&nbsp;&nbsp;&nbsp; 没有跨平台的基础库，就没有跨平台的动态模块加载机制；<br>&nbsp;&nbsp;&nbsp; John Spencer夭折的书《The Art of C Programming》，GoF的Interpreter模式；Little Language实际上具有反映计算机本质的一些东西，现在却成了很少为C++程序员所采用和熟悉的工具。</p>
<p>&nbsp;</p>
<p><strong>2005年，C++的现实处境</strong><br>&nbsp;●在系统编程领域仍然强势；<br>&nbsp;●套装软件主流开发语言之一；<br>&nbsp;●嵌入式开发领域进展较快；<br>&nbsp;●游戏引擎开发主力；<br>&nbsp;●科学计算方面略有一席之地<br>&nbsp;●遗留项目的维护；<br>&nbsp;●在企业应用开发领域快速收缩；<br>&nbsp;●Web开发中的影子语言；<br>&nbsp;●从高校主流教学中退潮；<br>&nbsp;●整体水平仍然不高，很多企业急于摆脱；<br>&nbsp;●最致命的：真正了解和熟练掌握C++的人太少；</p>
<p>案例：1. 国外一家公司花高薪聘人，要么能维护目前百万行规模的代码，要么把它转成Java；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2. IBM Workplace，项目一开始C++/Java并重，之后C++比重越来越小；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3. 微软与中国电信合作一个项目，客户端软件本来要用C++写，后来赶到产品化周期太长，改用C#，后发先至。&nbsp;</p>
<p><br><strong>问题何在<br></strong>&nbsp;●当前的软件产业发展的主要矛盾——各行各业对软件生产标准化、规模化、高质量要求与慢节奏、低效率、低质量的软件开发之间的矛盾。<br>&nbsp;●解决这个矛盾的关键：组件化体系，成熟的软件生产工具和环境，不断的创新精神。<br>&nbsp;●C++在外部环境已经发生根本变化的近十年时间里，没有抓住这个主要矛盾。</p>
<p><br><strong>重新评估我们的C++价值取向</strong><br>&nbsp;&nbsp;&nbsp; 重新评估&#8220;高级C++&#8221;的现实含义：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - 简洁有效优于惊世骇俗；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - 开放灵活优于保守固执；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - 帮助他人优于凸现自己；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - 领域创新优于卖弄技巧；</p>
<p>&nbsp;<br><strong>六个建议<br></strong>&nbsp;●学会与现实和谐共处；<br>&nbsp;●尽快面向不同领域建立跨平台构件标准；<br>&nbsp;●支持各领域已经形成的基础库不断完善；<br>&nbsp;●支持相关工具厂商，迅速完善工具链；<br>&nbsp;●支持动态语言的发展；<br>&nbsp;●面向产业挑战创新发展；</p>
<p>&nbsp;</p>
<p><strong>与现实和谐共处<br></strong>&nbsp;●承认C++只适合这个世界的一部分工作，快乐地与其他语言共同协作；<br>&nbsp;●告别妄自尊大和保守傲慢；<br>&nbsp;●尊重其他社群的专业能力和成绩；<br>&nbsp;●坦率承认C++在很多场合并非理想选择；<br>&nbsp;●在C++擅长的领域保持锐意。</p>
<p><br><strong>跨平台构件标准<br></strong>&nbsp;●C++迈向未来的关键技术步骤；<br>&nbsp;●尽可能支持现有的成熟方案；<br>&nbsp;●在不同尺度的平台上可能需要不同的标准；</p>
<p>&nbsp;</p>
<p><strong>支持成熟的基础库<br></strong>&nbsp;●基本组件：STL和Boost（部分）<br>&nbsp;●网络和系统编程：ACE<br>&nbsp;●分布式计算：ICE<br>&nbsp;●GUI：Qt<br>&nbsp;●Windows：MFC/ATL/WTL<br>&nbsp;●科学计算：MTL</p>
<p>&nbsp;</p>
<p><strong>完善工具链<br></strong>&nbsp;●C++用的GC；<br>&nbsp;●Code Review工具；<br>&nbsp;●内存错误排查工具；<br>&nbsp;●测试工具；<br>&nbsp;●MDA工具；<br>&nbsp;●文档工具；<br>&nbsp;●持续集成工具；<br>&nbsp;●运行录像工具。</p>
<p><br><strong>支持动态语言<br></strong>&nbsp;●动态语言是软件技术发展的一个重要方向，几年后会成为主流。<br>&nbsp;●目前几个流行动态语言天生与C/C++具有亲缘关系；<br>&nbsp;●加强对动态语言的友好性，是C++未来发展的一项重要任务；<br>&nbsp;●从这个角度来看待C++/CLI，我们应该持积极态度；<br>&nbsp;●Little Language问题；</p>
<p><br><strong>迎接产业新挑战</strong><br>&nbsp;●多核CPU带来根本性挑战，C++有责任挺身而出，为其他语言铺平前进道路；<br>&nbsp;●安全性问题，C/C++实际上是给整个产业拖了后腿，对此我们应当充分关注，积极改进；<br>&nbsp;●将STL思想精华发扬光大。<br></p>
<img src ="http://www.cppblog.com/andxie99/aggbug/22600.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/andxie99/" target="_blank">思勤无邪</a> 2007-04-22 19:50 <a href="http://www.cppblog.com/andxie99/archive/2007/04/22/22600.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.NET性能优化方面的总结（4） JavaScript</title><link>http://www.cppblog.com/andxie99/archive/2007/04/07/21449.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Sat, 07 Apr 2007 05:17:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/04/07/21449.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/21449.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/04/07/21449.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/21449.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/21449.html</trackback:ping><description><![CDATA[<p><br><strong>&nbsp;&nbsp;&nbsp; 4.1 JScript性能优化的基本原则</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;尽可能少地减少执行次数。毕竟对解释语言来说，每一个执行步骤，都需要和解释引擎做一次交互。<br><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;尽可能使用语言内置的功能，比如串链接。<br><strong>&nbsp;&nbsp;&nbsp; </strong>3.&nbsp;尽可能使用系统提供的API来进行优化。因为这些API是编译好的二进制代码，执行效率很高。<br><strong>&nbsp;&nbsp;&nbsp; </strong>4.&nbsp;书写最正确的代码。容错功能是要付出性能代价的。<br><br><strong>&nbsp;&nbsp;&nbsp; 4.2 JScript语言本身的优化</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>4.2.1 变量<br><strong>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;尽量使用局部变量。<br><strong>&nbsp;&nbsp;&nbsp; </strong>因为全局变量其实是全局对象的成员，而局部变量在栈上定义，优先查找，性能相对于全局变量要高。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;尽量在一个语句中做定义变量和赋值。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>3.&nbsp;省略不必要的变量定义。<br><strong>&nbsp;&nbsp;&nbsp; </strong>如果变量的定义可以被一个常量替代，就直接使用常量。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>4.&nbsp;使用Object语法对对象赋值。<br><strong>&nbsp;&nbsp;&nbsp; </strong>Object的赋值语法在操作复杂对象时效率更高。<br><strong>&nbsp;&nbsp;&nbsp; </strong>例如，可以将下面的代码：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">car&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Object();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>car.make&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Honda</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>car.model&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Civic</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>car.transmission&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">manual</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>car.miles&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100000</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>car.condition&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">needs&nbsp;work</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;</span></div>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>替换成：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_6_122_Open_Image onclick="this.style.display='none'; Codehighlighter1_6_122_Open_Text.style.display='none'; Codehighlighter1_6_122_Closed_Image.style.display='inline'; Codehighlighter1_6_122_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_6_122_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_6_122_Closed_Text.style.display='none'; Codehighlighter1_6_122_Open_Image.style.display='inline'; Codehighlighter1_6_122_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #000000">car&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span id=Codehighlighter1_6_122_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_6_122_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;make:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Honda</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;model:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Civic</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;transmission:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">manual</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;miles:&nbsp;</span><span style="COLOR: #000000">100000</span><span style="COLOR: #000000">,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;condition:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">needs&nbsp;work</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p><br><strong>&nbsp;&nbsp;&nbsp; 4.2.2 对象缓存<br>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;缓存对象查找的中间结果。<br><strong>&nbsp;&nbsp;&nbsp; </strong>因为JavaScript的解释性，所以a.b.c.d.e，需要进行至少4次查询操作，先检查a再检查a中的b，再检查b中的c，如此往下。所以如果这样的表达式重复出现，只要可能，应该尽量少出现这样的表达式，可以利用局部变量，把它放入一个临时的地方进行查询。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;缓存创建时间较长的对象。<br><strong>&nbsp;&nbsp;&nbsp; </strong>自定义高级对象和Date、RegExp对象在构造时都会消耗大量时间。如果可以复用，应采用缓存的方式。</p>
<p><strong>&nbsp;&nbsp;&nbsp; 4.2.3 字符串操作</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;使用"+=" 追加字符串，使用"+"来连接字符串。<br><strong>&nbsp;&nbsp;&nbsp; </strong>如果是追加字符串，最好使用s+=anotherStr操作，而不是要使用s=s+anotherStr。<br><strong>&nbsp;&nbsp;&nbsp; </strong>如果要连接多个字符串，应该使用"+"，如：<br><strong>&nbsp;&nbsp;&nbsp; </strong>s+=a;<br><strong>&nbsp;&nbsp;&nbsp; </strong>s+=b;<br><strong>&nbsp;&nbsp;&nbsp; </strong>s+=c;<br><strong>&nbsp;&nbsp;&nbsp; </strong>应该写成<br><strong>&nbsp;&nbsp;&nbsp; </strong>s+=a + b + c；</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;连接大量的字符串，应使用Array的join方法。<br><strong>&nbsp;&nbsp;&nbsp; </strong>如果是收集字符串，最好使用JavaScript数组缓存，最后使用join方法连接起来，如下：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;buf&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Array();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_53_83_Open_Image onclick="this.style.display='none'; Codehighlighter1_53_83_Open_Text.style.display='none'; Codehighlighter1_53_83_Closed_Image.style.display='inline'; Codehighlighter1_53_83_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_53_83_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_53_83_Closed_Text.style.display='none'; Codehighlighter1_53_83_Open_Image.style.display='inline'; Codehighlighter1_53_83_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_53_83_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_53_83_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;buf.push(i.toString());<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;all&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;buf.join(</span><span style="COLOR: #000000">""</span><span style="COLOR: #000000">);</span></div>
<p><br><strong>&nbsp;&nbsp;&nbsp; 4.2.4 类型转换<br>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;使用Math.floor()或者Math.round()将浮点数转换成整型。<br><strong>&nbsp;&nbsp;&nbsp; </strong>浮点数转换成整型，这个更容易出错，很多人喜欢使用parseInt()，其实parseInt()是用于将字符串转换成数字，而不是浮点数和整型之间的转换，我们应该使用Math.floor()或者Math.round()。<br>对象查找中的问题不一样，Math是内部对象，所以Math.floor()其实并没有多少查询方法和调用的时间，速度是最快的。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;自定义的对象，推荐定义和使用toString()方法来进行类型转换。<br><strong>&nbsp;&nbsp;&nbsp; </strong>对于自定义的对象，如果定义了toString()方法来进行类型转换的话，推荐显式调用toString()。因为内部的操作在尝试所有可能性之后，会尝试对象的toString()方法尝试能否转化为String，所以直接调用这个方法效率会更高。</p>
<p><strong>&nbsp;&nbsp;&nbsp; 4.2.5 循环的优化<br>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;尽可能少使用for(in)循环。<br><strong>&nbsp;&nbsp;&nbsp; </strong>在JavaScript中，我们可以使用for(;;),while(),for(in)三种循环，事实上，这三种循环中for(in)的效率极差，因为他需要查询散列键，只要可以就应该尽量少用。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;预先计算collection的length。<br><strong>&nbsp;&nbsp;&nbsp; </strong>如：将<br>&nbsp;&nbsp;&nbsp;&nbsp; for (var i = 0; i &lt; collection.length; i++)<br><strong>&nbsp;&nbsp;&nbsp; </strong>替换成：<br>&nbsp;&nbsp;&nbsp;&nbsp; for (var i = 0,&nbsp;len = collection.length; i &lt;&nbsp;len; i++)<br><strong>&nbsp;&nbsp;&nbsp; </strong>效果会更好，尤其是在大循环中。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>3.&nbsp;尽量减少循环内的操作。<br><strong>&nbsp;&nbsp;&nbsp; </strong>循环内的每个操作，都会被放大为循环次数的倍数。所以，大循环内微小的改进，在性能的整体提升上都是可观的。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>4.&nbsp;使用循环替代递归。<br>相比循环，递归的效率更差一些。递归的优点是在形式上更自然一些。所以，在不影响代码的维护性的前提下，用循环替代递归。</p>
<p><strong>&nbsp;&nbsp;&nbsp; 4.2.6 其它方面</strong><br><strong>&nbsp;&nbsp;&nbsp; </strong>1.&nbsp;尽量使用语言内置的语法。<br><strong>&nbsp;&nbsp;&nbsp; </strong>"var arr = [&#8230;];"和"var arr = new Array(&#8230;);"是等效的，但是前者的效能优于后者。同样，"var foo = {};"的方式也比"var foo = new Object();"快；"var reg = /../;"要比"var reg=new RegExp()"快。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>2.&nbsp;尽量不要使用eval。<br>使用eval，相当于在运行时再次调用解释引擎，对传入的内容解释运行，需要消耗大量时间。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>3.&nbsp;使用prototype代替closure。<br><strong>&nbsp;&nbsp;&nbsp; </strong>使用closure在性能和内存消耗上都是不利的。如果closure使用量过大，这就会成为一个问题。所以，尽量将：<br>&nbsp;&nbsp;&nbsp;&nbsp; this.methodFoo = function()<br>替换成：<br>&nbsp;&nbsp;&nbsp;&nbsp; MyClass.protoype.methodFoo = function()<br>和closure存在于对象实例之中不同，prototype存在于类中，被该类的所有的对象实例共享。</p>
<p><strong>&nbsp;&nbsp;&nbsp; </strong>4.&nbsp;避免使用with语句。<br><strong>&nbsp;&nbsp;&nbsp; </strong>With语句临时扩展对象查找的范围，节省了文字的录入时间，但付出了更多的执行时间。因为每个给出的名称都要在全局范围查找。所以，可以将下面的代码：</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">with</span><span style="COLOR: #000000">&nbsp;(document.formname)<br><img id=Codehighlighter1_25_79_Open_Image onclick="this.style.display='none'; Codehighlighter1_25_79_Open_Text.style.display='none'; Codehighlighter1_25_79_Closed_Image.style.display='inline'; Codehighlighter1_25_79_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_25_79_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_25_79_Closed_Text.style.display='none'; Codehighlighter1_25_79_Open_Image.style.display='inline'; Codehighlighter1_25_79_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_25_79_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_25_79_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;field1.value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">one</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;field2.value&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0