﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-白纸人生-随笔分类-C++</title><link>http://www.cppblog.com/andxie99/category/1882.html</link><description>上学时，因我年龄最小，个头也最小，上课时，就像大猩猩堆里的猴一般。如今，这猴偶尔也把最近的一些情况写在这里。</description><language>zh-cn</language><lastBuildDate>Tue, 20 May 2008 11:12:22 GMT</lastBuildDate><pubDate>Tue, 20 May 2008 11:12:22 GMT</pubDate><ttl>60</ttl><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>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>被误解的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>一个简单的不依靠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>0</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>什么是高级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>Ruminations on C++ 中的代理类Demo</title><link>http://www.cppblog.com/andxie99/archive/2007/03/29/20899.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Thu, 29 Mar 2007 14:44:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/03/29/20899.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/20899.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/03/29/20899.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/20899.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/20899.html</trackback:ping><description><![CDATA[看Ruminations on C++ 的时候照着写的，简单的框架，留作备份吧。<br><br>
<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: #008000">//</span><span style="COLOR: #008000">&nbsp;代理类&nbsp;Demo<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;将继承和容器共用，迫使我们要处理两个问题：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;控制内存分配和把不同类型的对象放入同一个容器中。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;代理类的每个对象都代表另一个对象，该对象可以是<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位于一个完整继承层次中的任何类的对象。通过在容器中<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;用代理对象而不是对象本身来解决以上两个问题</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">process.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;system()</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><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: #008000">//</span><span style="COLOR: #008000">&nbsp;所有交通工具的基类</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Vehicle<br><img id=Codehighlighter1_250_365_Open_Image onclick="this.style.display='none'; Codehighlighter1_250_365_Open_Text.style.display='none'; Codehighlighter1_250_365_Closed_Image.style.display='inline'; Codehighlighter1_250_365_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_250_365_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_250_365_Closed_Text.style.display='none'; Codehighlighter1_250_365_Open_Image.style.display='inline'; Codehighlighter1_250_365_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_250_365_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_250_365_Open_Text><span style="COLOR: #000000">{<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;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;start()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;动态复制</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;Vehicle</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;copy()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;虚析构函数</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_362_363_Open_Image onclick="this.style.display='none'; Codehighlighter1_362_363_Open_Text.style.display='none'; Codehighlighter1_362_363_Closed_Image.style.display='inline'; Codehighlighter1_362_363_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_362_363_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_362_363_Closed_Text.style.display='none'; Codehighlighter1_362_363_Open_Image.style.display='inline'; Codehighlighter1_362_363_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">Vehicle()&nbsp;</span><span id=Codehighlighter1_362_363_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_362_363_Open_Text><span style="COLOR: #000000">{}</span></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></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;交通工具的代理类</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;VehicleSurrogate<br><img id=Codehighlighter1_404_694_Open_Image onclick="this.style.display='none'; Codehighlighter1_404_694_Open_Text.style.display='none'; Codehighlighter1_404_694_Closed_Image.style.display='inline'; Codehighlighter1_404_694_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_404_694_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_404_694_Closed_Text.style.display='none'; Codehighlighter1_404_694_Open_Image.style.display='inline'; Codehighlighter1_404_694_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_404_694_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_404_694_Open_Text><span style="COLOR: #000000">{<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;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;无参构造函数，用于创建数组</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;VehicleSurrogate();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;用Vehicle&nbsp;及其派生类构造</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;VehicleSurrogate(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Vehicle</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">VehicleSurrogate();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;拷贝及赋值</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;VehicleSurrogate(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;VehicleSurrogate</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;VehicleSurrogate</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">operator</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;VehicleSurrogate</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Vehicle&nbsp;的方法</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;start();<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;&nbsp;&nbsp;Vehicle</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;p;<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 id=Codehighlighter1_742_743_Open_Image onclick="this.style.display='none'; Codehighlighter1_742_743_Open_Text.style.display='none'; Codehighlighter1_742_743_Closed_Image.style.display='inline'; Codehighlighter1_742_743_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_742_743_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_742_743_Closed_Text.style.display='none'; Codehighlighter1_742_743_Open_Image.style.display='inline'; Codehighlighter1_742_743_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>VehicleSurrogate::VehicleSurrogate()&nbsp;:&nbsp;p(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)&nbsp;</span><span id=Codehighlighter1_742_743_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_742_743_Open_Text><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_813_814_Open_Image onclick="this.style.display='none'; Codehighlighter1_813_814_Open_Text.style.display='none'; Codehighlighter1_813_814_Closed_Image.style.display='inline'; Codehighlighter1_813_814_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_813_814_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_813_814_Closed_Text.style.display='none'; Codehighlighter1_813_814_Open_Image.style.display='inline'; Codehighlighter1_813_814_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>VehicleSurrogate::VehicleSurrogate(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Vehicle</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;v)&nbsp;:&nbsp;p(v.copy())&nbsp;</span><span id=Codehighlighter1_813_814_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_813_814_Open_Text><span style="COLOR: #000000">{}</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>VehicleSurrogate::VehicleSurrogate(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;VehicleSurrogate</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;vs)&nbsp;<br><img id=Codehighlighter1_910_911_Open_Image onclick="this.style.display='none'; Codehighlighter1_910_911_Open_Text.style.display='none'; Codehighlighter1_910_911_Closed_Image.style.display='inline'; Codehighlighter1_910_911_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_910_911_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_910_911_Closed_Text.style.display='none'; Codehighlighter1_910_911_Open_Image.style.display='inline'; Codehighlighter1_910_911_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>:&nbsp;p(vs.p&nbsp;</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">&nbsp;vs.p</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">copy()&nbsp;:&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)&nbsp;</span><span id=Codehighlighter1_910_911_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_910_911_Open_Text><span style="COLOR: #000000">{}</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>VehicleSurrogate&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;VehicleSurrogate::</span><span style="COLOR: #0000ff">operator</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;VehicleSurrogate</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;vs)<br><img id=Codehighlighter1_990_1072_Open_Image onclick="this.style.display='none'; Codehighlighter1_990_1072_Open_Text.style.display='none'; Codehighlighter1_990_1072_Closed_Image.style.display='inline'; Codehighlighter1_990_1072_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_990_1072_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_990_1072_Closed_Text.style.display='none'; Codehighlighter1_990_1072_Open_Image.style.display='inline'; Codehighlighter1_990_1072_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_990_1072_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_990_1072_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(p&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;vs.p)<br><img id=Codehighlighter1_1009_1055_Open_Image onclick="this.style.display='none'; Codehighlighter1_1009_1055_Open_Text.style.display='none'; Codehighlighter1_1009_1055_Closed_Image.style.display='inline'; Codehighlighter1_1009_1055_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1009_1055_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1009_1055_Closed_Text.style.display='none'; Codehighlighter1_1009_1055_Open_Image.style.display='inline'; Codehighlighter1_1009_1055_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1009_1055_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_1009_1055_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;p;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;vs.p&nbsp;</span><span style="COLOR: #000000">?</span><span style="COLOR: #000000">&nbsp;vs.p</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">copy()&nbsp;:&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">;<br><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 id=Codehighlighter1_1113_1125_Open_Image onclick="this.style.display='none'; Codehighlighter1_1113_1125_Open_Text.style.display='none'; Codehighlighter1_1113_1125_Closed_Image.style.display='inline'; Codehighlighter1_1113_1125_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_1113_1125_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1113_1125_Closed_Text.style.display='none'; Codehighlighter1_1113_1125_Open_Image.style.display='inline'; Codehighlighter1_1113_1125_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>VehicleSurrogate::</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">VehicleSurrogate()&nbsp;</span><span id=Codehighlighter1_1113_1125_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_1113_1125_Open_Text><span style="COLOR: #000000">{&nbsp;delete&nbsp;p;&nbsp;}</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">void</span><span style="COLOR: #000000">&nbsp;VehicleSurrogate::start()<br><img id=Codehighlighter1_1159_1216_Open_Image onclick="this.style.display='none'; Codehighlighter1_1159_1216_Open_Text.style.display='none'; Codehighlighter1_1159_1216_Closed_Image.style.display='inline'; Codehighlighter1_1159_1216_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_1159_1216_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1159_1216_Closed_Text.style.display='none'; Codehighlighter1_1159_1216_Open_Image.style.display='inline'; Codehighlighter1_1159_1216_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_1159_1216_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_1159_1216_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(p)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">start();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Error</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<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">class</span><span style="COLOR: #000000">&nbsp;RoadVehicle&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Vehicle<br><img id=Codehighlighter1_1254_1420_Open_Image onclick="this.style.display='none'; Codehighlighter1_1254_1420_Open_Text.style.display='none'; Codehighlighter1_1254_1420_Closed_Image.style.display='inline'; Codehighlighter1_1254_1420_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_1254_1420_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1254_1420_Closed_Text.style.display='none'; Codehighlighter1_1254_1420_Open_Image.style.display='inline'; Codehighlighter1_1254_1420_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_1254_1420_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_1254_1420_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;start()<br><img id=Codehighlighter1_1280_1323_Open_Image onclick="this.style.display='none'; Codehighlighter1_1280_1323_Open_Text.style.display='none'; Codehighlighter1_1280_1323_Closed_Image.style.display='inline'; Codehighlighter1_1280_1323_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1280_1323_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1280_1323_Closed_Text.style.display='none'; Codehighlighter1_1280_1323_Open_Image.style.display='inline'; Codehighlighter1_1280_1323_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1280_1323_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_1280_1323_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">RoadVehicle&nbsp;start.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Vehicle</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;copy()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_1349_1396_Open_Image onclick="this.style.display='none'; Codehighlighter1_1349_1396_Open_Text.style.display='none'; Codehighlighter1_1349_1396_Closed_Image.style.display='inline'; Codehighlighter1_1349_1396_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1349_1396_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1349_1396_Closed_Text.style.display='none'; Codehighlighter1_1349_1396_Open_Image.style.display='inline'; Codehighlighter1_1349_1396_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1349_1396_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_1349_1396_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;(Vehicle</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;RoadVehicle(</span><span style="COLOR: #000000">*</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">RoadVehicle()<br><img id=Codehighlighter1_1415_1418_Open_Image onclick="this.style.display='none'; Codehighlighter1_1415_1418_Open_Text.style.display='none'; Codehighlighter1_1415_1418_Closed_Image.style.display='inline'; Codehighlighter1_1415_1418_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1415_1418_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1415_1418_Closed_Text.style.display='none'; Codehighlighter1_1415_1418_Open_Image.style.display='inline'; Codehighlighter1_1415_1418_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1415_1418_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_1415_1418_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></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></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;AutoVehicle&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;RoadVehicle<br><img id=Codehighlighter1_1463_1629_Open_Image onclick="this.style.display='none'; Codehighlighter1_1463_1629_Open_Text.style.display='none'; Codehighlighter1_1463_1629_Closed_Image.style.display='inline'; Codehighlighter1_1463_1629_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_1463_1629_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1463_1629_Closed_Text.style.display='none'; Codehighlighter1_1463_1629_Open_Image.style.display='inline'; Codehighlighter1_1463_1629_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_1463_1629_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_1463_1629_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;start()<br><img id=Codehighlighter1_1489_1532_Open_Image onclick="this.style.display='none'; Codehighlighter1_1489_1532_Open_Text.style.display='none'; Codehighlighter1_1489_1532_Closed_Image.style.display='inline'; Codehighlighter1_1489_1532_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1489_1532_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1489_1532_Closed_Text.style.display='none'; Codehighlighter1_1489_1532_Open_Image.style.display='inline'; Codehighlighter1_1489_1532_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1489_1532_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_1489_1532_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">AutoVehicle&nbsp;start.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Vehicle</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;copy()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_1558_1605_Open_Image onclick="this.style.display='none'; Codehighlighter1_1558_1605_Open_Text.style.display='none'; Codehighlighter1_1558_1605_Closed_Image.style.display='inline'; Codehighlighter1_1558_1605_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1558_1605_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1558_1605_Closed_Text.style.display='none'; Codehighlighter1_1558_1605_Open_Image.style.display='inline'; Codehighlighter1_1558_1605_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1558_1605_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_1558_1605_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;(Vehicle</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;AutoVehicle(</span><span style="COLOR: #000000">*</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">AutoVehicle()<br><img id=Codehighlighter1_1624_1627_Open_Image onclick="this.style.display='none'; Codehighlighter1_1624_1627_Open_Text.style.display='none'; Codehighlighter1_1624_1627_Closed_Image.style.display='inline'; Codehighlighter1_1624_1627_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1624_1627_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1624_1627_Closed_Text.style.display='none'; Codehighlighter1_1624_1627_Open_Image.style.display='inline'; Codehighlighter1_1624_1627_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1624_1627_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_1624_1627_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></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></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_1645_1853_Open_Image onclick="this.style.display='none'; Codehighlighter1_1645_1853_Open_Text.style.display='none'; Codehighlighter1_1645_1853_Closed_Image.style.display='inline'; Codehighlighter1_1645_1853_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_1645_1853_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1645_1853_Closed_Text.style.display='none'; Codehighlighter1_1645_1853_Open_Image.style.display='inline'; Codehighlighter1_1645_1853_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_1645_1853_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_1645_1853_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;VehicleSurrogate&nbsp;pa[</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;RoadVehicle</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;prv&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;RoadVehicle();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pa[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">prv;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;prv;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pa[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;AutoVehicle();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pa[</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;RoadVehicle();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pa[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">].start();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pa[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">].start();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pa[</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">].start();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</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>
<img src ="http://www.cppblog.com/andxie99/aggbug/20899.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-03-29 22:44 <a href="http://www.cppblog.com/andxie99/archive/2007/03/29/20899.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>类厂和COM类的关系</title><link>http://www.cppblog.com/andxie99/archive/2007/03/07/19341.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Wed, 07 Mar 2007 02:24:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/03/07/19341.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/19341.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/03/07/19341.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/19341.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/19341.html</trackback:ping><description><![CDATA[读过《COM技术内幕》，理一下用类厂创建COM类的过程以及之间的关系。<br><br>类厂用来抽象组件的create过程，客户不需要知道组件的详细情况，也不需要知道类厂的详细情况，只要知道CoCreateInstance可以创建组件即可。而CoCreateInstance内部调用DllGetClassObject来生成该组件的类厂，由于类厂有组件的作者撰写，所以对组件类可谓知根知底，由类厂来生成组件完全行得通，这样客户和组件就进一步划分，客户只能查询该组件是否支持某接口，而对组件的其他情况一无所知，这样的划分可以使组件和客户间的耦合更小。<br>组件如果将某接口的全部方法都实现了，就称该组件支持某接口，com并没有规定组件和接口之间是虚函数继承的关系，只是在c++中以这种方法来实现最好而已。 &nbsp; <br>&nbsp; IClassFactory说穿了就是专门构造组件的类，这样做是为了抽象，因为客户没有必要知道组件是什么，如果由客户直接构造组件，客户势必要知道组件的信息，com就失去了它的意义了，所以，规定了一个类厂（支持IClassFactory接口），每个组件的类厂都很清楚并且也只清楚该组件的信息，而客户只需要调用com库函数CoCreateInstance就可以了。&nbsp;&nbsp;&nbsp;<br>&nbsp; 创建流程图： &nbsp; <br>&nbsp; CoCreateInstance &nbsp; --&gt;&gt; &nbsp; CoGetClassObject &nbsp; --&gt;&gt; &nbsp; DllGetClassObject &nbsp; --&gt;&gt; &nbsp; new &nbsp; ClassFactory&nbsp;&nbsp;&nbsp; --&gt;&gt;IClassFactory::CreateInstance() &nbsp; --&gt;&gt; &nbsp; new &nbsp; Component 
<img src ="http://www.cppblog.com/andxie99/aggbug/19341.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-03-07 10:24 <a href="http://www.cppblog.com/andxie99/archive/2007/03/07/19341.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用IDropTarget接口同时支持文本和文件拖放（转）</title><link>http://www.cppblog.com/andxie99/archive/2007/03/05/19228.html</link><dc:creator>思勤无邪</dc:creator><author>思勤无邪</author><pubDate>Mon, 05 Mar 2007 04:52:00 GMT</pubDate><guid>http://www.cppblog.com/andxie99/archive/2007/03/05/19228.html</guid><wfw:comment>http://www.cppblog.com/andxie99/comments/19228.html</wfw:comment><comments>http://www.cppblog.com/andxie99/archive/2007/03/05/19228.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/andxie99/comments/commentRss/19228.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/andxie99/services/trackbacks/19228.html</trackback:ping><description><![CDATA[<p align=justify>&nbsp;最近在写Shell Extension方面的东西，看到了这篇文章，抄在这里。<br>原文地址<a href="http://blog.csdn.net/vcbear/archive/2002/01/25/5990.aspx">http://blog.csdn.net/vcbear/archive/2002/01/25/5990.aspx</a><br>同时也找到了一个与Drag and Drop有关的例子，地址：<a href="http://www.codeproject.com/useritems/NSExtDragDrop.asp">http://www.codeproject.com/useritems/NSExtDragDrop.asp</a></p>
<font lang=ZH-CN face=宋体 size=3>
<p align=justify></p>
</font><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#118;&#99;&#98;&#101;&#97;&#114;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;"><font face="宋体, MS Song" size=4>vcbear</font> </a><font lang=ZH-CN face=宋体>
<p align=justify>关于</p>
</font><font face="宋体, MS Song">Windows</font> <font lang=ZH-CN face=宋体>的外壳扩展编程，拖放是比较简单的一种，在网上可以找到不少介绍这个技巧的文章。大部分是介绍使用</font> <font face="宋体, MS Song">MFC</font> <font lang=ZH-CN face=宋体>的</font> <font face="宋体, MS Song">COleDropTarget</font> <font lang=ZH-CN face=宋体>实现的，我觉得一般使用</font> <font face="宋体, MS Song">COleDropTarget</font> <font lang=ZH-CN face=宋体>已经很好了，但是我习惯在一些程序模块中，完全的不使用</font> <font face="宋体, MS Song">MFC,</font> <font lang=ZH-CN face=宋体>比如纯</font> <font face="宋体, MS Song">SDK</font> <font lang=ZH-CN face=宋体>编程</font> <font face="宋体, MS Song">,</font> <font lang=ZH-CN face=宋体>还有用在</font> <font face="宋体, MS Song">ATL</font> <font lang=ZH-CN face=宋体>的时候</font> <font face="宋体, MS Song">,MFC</font> <font lang=ZH-CN face=宋体>是相当累赘的。所以</font> <font face="宋体, MS Song">COleDropTarget</font> <font lang=ZH-CN face=宋体>在这个意义上讲不够完美。
<p align=justify>参考了</p>
</font><font face="宋体, MS Song">MSDN</font> <font lang=ZH-CN face=宋体>以及</font> <a href="http://www.codeproject.com/"><font face="宋体, MS Song">www.CodeProject.com</font> </a><font lang=ZH-CN face=宋体>的相关文章和代码（</font> <strong><font face="宋体, MS Song">by Thomas Blenkers</font> </strong><font lang=ZH-CN face=宋体>）之后，我发现拖放实际上主要使用了</font> <font face="宋体, MS Song">IDropTarget</font> <font lang=ZH-CN face=宋体>的接口方法，非常简单，不妨直接面对原始</font> <font face="宋体, MS Song">IDropTarget</font> <font lang=ZH-CN face=宋体>实现自己的拖放类。
<p align=justify>作为学习笔记，就有了这么一篇文字,以抛砖引玉：</p>
</font><strong><font color=#0000ff>
<p align=justify>IDropTarget</p>
</font></strong><font lang=ZH-CN face=宋体>是系统留给支持拖放的客户程序的一个纯虚接口，事先没有对接口的任何函数进行实现，而是让用户通过实现接口函数来接管拖放的结果。</font>IDropTarget<font lang=ZH-CN face=宋体>接口有以下成员函数：
<ul>
    <p align=justify></p>
    <li>基本</li>
</ul>
</font><font face="宋体, MS Song">COM</font><font lang=ZH-CN face=宋体>成员函数
<p>&#160;</p>
<dir>
<dir></dir></dir></font><strong><font color=#0000ff>
<p align=justify>QueryInterface </p>
<p align=justify>AddRef </p>
<p align=justify>Release </p>
<ul></ul>
    </font></strong><font lang=ZH-CN face=宋体>
    <p align=justify></p>
    <li>接管拖放事件的成员函数：
    <p>&#160;</p>
    <dir>
    <dir></dir></dir></font><strong><font color=#0000ff>
    <p align=justify>DragEnter</p>
    <p align=justify>DragOver</p>
    <p align=justify>DragLeave</p>
    <p align=justify>Drop</p>
    </font></strong><font lang=ZH-CN face=宋体>
    <p align=justify>也就是说，要在客户程序里实现以上</p>
    </font><font face="宋体, MS Song">7</font><font lang=ZH-CN face=宋体>个函数的实体。
    <p align=justify>系统在检测到拖放发生的时候，会在合适的时候依次调用客户程序里实现的</p>
    </font><font face="宋体, MS Song">IDropTarget</font><font lang=ZH-CN face=宋体>接口相应函数，检查用户在这些函数里返回的标志，决定鼠标外观表现和拖放结果。</font><font lang=ZH-CN face=宋体 size=3>
    <p>&#160;</p>
    <hr>
    <p>&#160;</p>
    </font><strong><font lang=ZH-CN face=宋体>
    <p align=justify>　</p>
    <p align=justify>实现</p>
    </font><font face="宋体, MS Song">IDropTarget</font><font lang=ZH-CN face=宋体>接口</font></strong><br>为此建立一个基类为<font face="宋体, MS Song">IDropTarget</font><font lang=ZH-CN face=宋体>的类：</font><strong><font face="宋体, MS Song"></font>
    <p align=justify>class CDropTargetEx : public IDropTarget </p>
    </strong>
    <p align=justify>IDropTarget<font lang=ZH-CN face=宋体>接口在</font>OLEIDL.h<font lang=ZH-CN face=宋体>里定义，为纯虚接口。</font></p>
    <p align=justify>在<font face="宋体, MS Song">CDropTargetEx</font><font lang=ZH-CN face=宋体>里依次声明接口所包含的</font><font face="宋体, MS Song">7</font><font lang=ZH-CN face=宋体>个函数，原形为：</font></p>
    <font color=#0000ff>
    <p align=justify>HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject);</p>
    <p align=justify>ULONG STDMETHODCALLTYPE AddRef(void);</p>
    <p align=justify>ULONG STDMETHODCALLTYPE Release(void);</p>
    <p align=justify>HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, </p>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <p align=justify>POINTL pt, </p>
    <p align=justify>DWORD *pdwEffect);</p>
    </dir></dir></dir></dir></dir></dir></dir></dir>
    <p align=justify>HRESULT STDMETHODCALLTYPE DragEnter(IDataObject * pDataObject, </p>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <dir>
    <p align=