﻿<?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++ Programmer's Cookbook-随笔分类-CPlusPlus</title><link>http://www.cppblog.com/mzty/category/199.html</link><description>&lt;a href = "http://www.cppblog.com/mzty/archive/2007/03/02/19109.html"&gt;&lt;font size = 3 &gt;{C++ 基础}&lt;font/&gt;&lt;/a&gt;

&lt;a href = "http://www.cppblog.com/mzty/archive/2007/08/13/29922.html"&gt;&lt;font size = 3 &gt;{C++ 高级}&lt;font/&gt;&lt;/a&gt;

&lt;a href = "http://www.cppblog.com/mzty/archive/2007/04/16/22064.html"&gt;&lt;font size = 3 &gt;{C#界面，C++核心算法}&lt;font/&gt;&lt;/a&gt;

&lt;a href = "http://www.cppblog.com/mzty/archive/2007/03/04/19163.html"&gt;&lt;font size = 3 &gt;{设计模式}&lt;font/&gt;&lt;/a&gt;

&lt;a href = "
http://www.cppblog.com/mzty/archive/2007/03/04/19167.html"&gt;&lt;font size = 3 &gt;{C#基础}&lt;font/&gt;&lt;/a&gt;





</description><language>zh-cn</language><lastBuildDate>Mon, 15 Jul 2013 05:54:28 GMT</lastBuildDate><pubDate>Mon, 15 Jul 2013 05:54:28 GMT</pubDate><ttl>60</ttl><item><title>动态链接库dll 静态链接库lib 动态导入库lib</title><link>http://www.cppblog.com/mzty/archive/2013/07/15/201811.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Mon, 15 Jul 2013 05:38:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2013/07/15/201811.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/201811.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2013/07/15/201811.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/201811.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/201811.html</trackback:ping><description><![CDATA[<p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br />转自：<a href="http://blog.csdn.net/uniqueren/article/details/4163662">http://blog.csdn.net/uniqueren/article/details/4163662</a><br /><br />目前以lib后缀的库有两种，一种为<span style="color: #ff0000;">静态链接库(Static Libary，以下简称&#8220;静态库&#8221;)</span>&nbsp;，另一种为<span style="color: #ff0000;">动态连接库(DLL，以下简称&#8220;动态库&#8221;)</span>&nbsp;的<span style="color: #ff0000;">导入库(Import Libary，以下简称&#8220;导入库&#8221;)</span>&nbsp;。&nbsp;<br />静态库是一个或者多个obj文件的打包，所以有人干脆把从obj文件生成lib的过程称为Archive，即合并到一起。比如你链接一个静态库，如果其中有错，它会准确的找到是哪个obj有错，即静态lib只是壳子。&nbsp;<br />动态库一般会有对应的导入库，方便程序静态载入动态链接库，否则你可能就需要自己LoadLibary调入DLL文件，然后再手工GetProcAddress获得对应函数了。有了导入库，你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。&nbsp;<br /><span style="color: #ff0000;">导入库和静态库</span>&nbsp;的区别很大，他们实质是不一样的东西。<span style="text-decoration: underline;">静态库本身就包含了实际执行代码、符号表等等</span>&nbsp;，而对于<span style="text-decoration: underline;">导入库而言，其实际的执行代码位于动态库中，导入库只包含了地址符号表等，确保程序找到对应函数的一些基本地址信息</span>&nbsp;。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">这也是实际上很多开源代码发布的惯用方式：</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">1. 预编译的开发包：包含一些.dll文件和一些.lib文件。其中这里的.lib就是导入库，而不要错以为是静态库。但是引入方式和静态库一样，要在链接路 径上添加找到这些.lib的路径。而.dll则最好放到最后产生的应用程序exe执行文件相同的目录。这样运行时，就会自动调入动态链接库。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">2. 用户自己编译： 下载的是源代码，按照readme自己编译。生成很可能也是.dll + .lib(导入库)的库文件</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">3. 如果你只有dll，并且你知道dll中函数的函数原型，那么你可以直接在自己程序中使用LoadLibary调入DLL文件，GetProcAddress</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">DLL：&nbsp;<br />动 态链接库 (DLL) 是作为共享函数库的可执行文件。动态链接提供了一种方法，使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 中，该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个 DLL 副本的内容。&nbsp;<br />动态链接与静态链接的不同之处在于它允许可执行模块（.dll 文件或 .exe 文件）仅包含在运行时定位 DLL 函数的可执行代码所需的信息。在静态链接中，链接器从静态链接库获取所有被引用的函数，并将库同代码一起放到可执行文件中。&nbsp;<br />使用动态链接代替静态链接有若干优点。DLL 节省内存，减少交换操作，节省磁盘空间，更易于升级，提供售后支持，提供扩展 MFC 库类的机制，支持多语言程序，并使国际版本的创建轻松完成。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">API 就是应用程序编程接口。它是能用来操作组件、应用程序或者操作系统的一组函数。典型的情况下，API 由一个或多个提供某种特殊功能的 DLL 组成。&nbsp;<br />DLL 是一个文件，其中包含了在 Microsoft? Windows? 下运行的任何应用程序都可调用的函数。运行时，DLL 中的函数动态地链接到调用它的应用程序中。无论有多少应用程序调用 DLL 中的某个函数，在磁盘上只有一个文件包含该函数，且只在它调入内存时才创建该 DLL。&nbsp;<br />您听到最多的 API 可能是 Windows API，它包括构成 Windows 操作系统的各种 DLL。每个 Windows 应用程序都直接或间接地与 Windows API 互动。Windows API 保证 Windows 下运行的所有应用程序的行为方式一致。&nbsp;<br />注意 随着 Windows 操作系统的发展，现已发布了几个版本的 Windows API。Windows 3.1 使用 Win16 API。Microsoft? Windows NT?、Windows 95 和 Windows 98 平台使用 Microsoft? Win32? API。&nbsp;<br />除 Windows API 外，其他一些 API 也已发布。例如，邮件应用程序编程接口 (MAPI) 是一组可用于编写电子邮件应用程序的 DLL。&nbsp;<br />API 传统上是为开发 Windows 应用程序的 C 和 C++ 程序员编写的，但其他的编程语言（包括VBA）也可以调用 DLL 中的函数。因为大部分 DLL 主要是为 C 和 C++ 程序员编写和整理说明的，所以调用 DLL 函数的方法与调用 VBA 函数会有所不同。在使用 API 时必须了解如何给 DLL 函数传递参数。&nbsp;<br />警告 调用 Windows API 和 其他 DLL 函数可能会给您的应用程序带来不良影响。从自己的代码中直接调用 DLL 函数时，您绕过了 VBA 通常提供的一些安全机制。如果在定义或调用 DLL 函数时出现错误（所有程序员都不可避免），可能会在应用程序中引起应用程序错误（也称为通用性保护错误，或 GPF）。最好的解决办法是在运行代码以前保存该项目，并确保了解 DLL 函数调用的原理。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">LIB 创建标准库、导入库和导出文件，在生成 32 位程序时可将它们与 LINK 一起使用。LIB 从命令提示运行。&nbsp;<br />可在下列几种模式下使用 LIB：&nbsp;<br />生成或修改 COFF 库&nbsp;<br />将成员对象提取到文件中&nbsp;<br />创建导出文件和导入库&nbsp;<br />这些模式是互斥的；每次只能以一种模式使用 LIB。</p><img src ="http://www.cppblog.com/mzty/aggbug/201811.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2013-07-15 13:38 <a href="http://www.cppblog.com/mzty/archive/2013/07/15/201811.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>2道C++面试题</title><link>http://www.cppblog.com/mzty/archive/2010/12/21/137134.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Tue, 21 Dec 2010 12:59:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2010/12/21/137134.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/137134.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2010/12/21/137134.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/137134.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/137134.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<p>一 逻辑题</p>
<p><br>在一张东景照片上,人们分别戴着帽子,系着围巾和戴着者手套.只戴帽子的人数与只系围巾和只戴手套的人数相等:只有4人没有戴帽子:戴着帽子和系着围巾,但没有戴手套的有5人:只戴帽子的人数两倍于只系围巾者:未戴手套者8人,未系围巾者7人:三样东西都用上了的人比只戴帽子的人多一个.那么请问:多少人同时用上了帽子,围巾和手套?多少人只戴了手套?多少人只系了围巾?多少人既戴了帽子,又戴了手套,但没系围巾?多少人戴着手套?照片上一共有多少个人?<br><br>如果用纯代数的方法来做，就这样。 <br>设：只戴帽子的人数为A，只围巾B，只手套C，只帽子围巾D，只帽子手套E，只围巾手套F，都带的G 得： <br>A=B+C（只戴帽子人数与只系围巾和只戴手套的人数和相等 ） <br>B+C+F=4 （只有4人没有戴帽子） <br>D=5（戴着帽子和系着围巾，但没有戴手套的有5人） <br>A=2B（只戴帽子的人数两倍于只系着巾） <br>A+B+D=8（未戴着手套者8人） <br>A+C+E=7（未系围巾者7人） <br>G=A+1 （三样东西都用上了的人比只戴帽子的人多一个） <br>从D=5 A=2B A+B+D=8 这3个式子开始解 <br>最后得出A=2 B=1 C=1 D=5 E=4 F=2 G=3&nbsp;<br><br><br><br>二 汉诺塔<br></p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">#include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></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 align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Hanoi(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;n,</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;A,</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;B,</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;C);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_112_140_Open_Image onclick="this.style.display='none'; Codehighlighter1_112_140_Open_Text.style.display='none'; Codehighlighter1_112_140_Closed_Image.style.display='inline'; Codehighlighter1_112_140_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_112_140_Closed_Image onclick="this.style.display='none'; Codehighlighter1_112_140_Closed_Text.style.display='none'; Codehighlighter1_112_140_Open_Image.style.display='inline'; Codehighlighter1_112_140_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_112_140_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_112_140_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;Hanoi(</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">A</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">B</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">C</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Hanoi(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;n,</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;A,</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;B,</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;C)<br><img id=Codehighlighter1_182_400_Open_Image onclick="this.style.display='none'; Codehighlighter1_182_400_Open_Text.style.display='none'; Codehighlighter1_182_400_Closed_Image.style.display='inline'; Codehighlighter1_182_400_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_182_400_Closed_Image onclick="this.style.display='none'; Codehighlighter1_182_400_Closed_Text.style.display='none'; Codehighlighter1_182_400_Open_Image.style.display='inline'; Codehighlighter1_182_400_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_182_400_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_182_400_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(n</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Move&nbsp;top&nbsp;disk&nbsp;from&nbsp;peg&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">A</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;to&nbsp;peg&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">C</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">endl;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_275_398_Open_Image onclick="this.style.display='none'; Codehighlighter1_275_398_Open_Text.style.display='none'; Codehighlighter1_275_398_Closed_Image.style.display='inline'; Codehighlighter1_275_398_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_275_398_Closed_Image onclick="this.style.display='none'; Codehighlighter1_275_398_Closed_Text.style.display='none'; Codehighlighter1_275_398_Open_Image.style.display='inline'; Codehighlighter1_275_398_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_275_398_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_275_398_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Hanoi(n</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,A,C,B);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Move&nbsp;top&nbsp;disk&nbsp;from&nbsp;peg&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">A</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;to&nbsp;peg&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">C</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">endl;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Hanoi(n</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,B,A,C);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span></div>
<br>完！<img src ="http://www.cppblog.com/mzty/aggbug/137134.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2010-12-21 20:59 <a href="http://www.cppblog.com/mzty/archive/2010/12/21/137134.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.h头文件 .lib库文件 .dll动态链接库文件关系</title><link>http://www.cppblog.com/mzty/archive/2010/11/28/134901.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Sun, 28 Nov 2010 09:12:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2010/11/28/134901.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/134901.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2010/11/28/134901.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/134901.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/134901.html</trackback:ping><description><![CDATA[<p><br>原帖地址：<a href="http://blog.csdn.net/c395565746c/archive/2010/03/21/5402239.aspx">http://blog.csdn.net/c395565746c/archive/2010/03/21/5402239.aspx</a></p>
<p><br>.h头文件是编译时必须的，lib是链接时需要的，dll是运行时需要的。</p>
<p>附加依赖项的是.lib不是.dll，若生成了DLL,则肯定也生成 LIB文件。如果要完成源代码的编译和链接，有头文件和lib就够了。如果也使动态连接的程序运行起来，有dll就够了。在开发和调试阶段，当然最好都有。</p>
<p>.h .lib .dll三者的关系是：</p>
<p>H文件作用是:声明函数接口&nbsp; </p>
<p>DLL文件作用是: 函数可执行代码&nbsp; </p>
<p>当我们在自己的程序中引用了一个H文件里的函数,编链器怎么知道该调用哪个DLL文件呢?这就是LIB文件的作用: 告诉链接器 调用的函数在哪个DLL中，函数执行代码在DLL中的什么位置 ，这也就是为什么需要附加依赖项 .LIB文件，它起到桥梁的作用。如果生成静态库文件，则没有DLL ，只有lib，这时函数可执行代码部分也在lib文件中</p>
<p>目前以lib后缀的库有两种，一种为静态链接库(Static Libary，以下简称&#8220;静态库&#8221;)，另一种为动态连接库(DLL，以下简称&#8220;动态库&#8221;)的导入库(Import Libary，以下简称&#8220;导入库&#8221;）。静态库是一个或者多个obj文件的打包 ，所以有人干脆把从obj文件生成lib的过程称为Archive，即合并到一起。比如你链接一个静态库，如果其中有错，它会准确的找到是哪个obj有错，即静态lib只是壳子。动态库一般会有对应的导入库，方便程序静态载入动态链接库 ，否则你可能就需要自己LoadLibary调入DLL文件，然后再手工GetProcAddress获得对应函数了。有了导入库，你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。导入库和静态库的区别很大，他们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等，而对于导入库而言，其实际的执行代码位于动态库中，导入库只包含了地址符号表等，确保程序找到对应函数的一些基本地址信息。</p>
<p>一般的动态库程序有lib文件和dll文件。lib文件是必须在编译期就连接到应用程序中的，而dll文件是运行期才会被调用的。 如果有dll文件，那么对应的lib文件一般是一些索引信息，具体的实现在dll文件中。如果只有lib文件，那么这个lib文件是静态编译出来的，索引和实现都在其中。静态编译的lib文件有好处：给用户安装时就不需要再挂动态库了。但也有缺点，就是导致应用程序比较大，而且失去了动态库的灵活性，在版本升级时，同时要发布新的应用程序才行。在动态库的情况下，有两个文件，而一个是引入库（.LIB）文件，一个是DLL文件，引入库文件包含被DLL导出的函数的名称和位置，DLL包含实际的函数和数据，应用程序使用LIB文件链接到所需要使用的DLL文件，库中的函数和数据并不复制到可执行文件中，因此在应用程序的可执行文件中，存放的不是被调用的函数代码，而是DLL中所要调用的函数的内存地址，这样当一个或多个应用程序运行是再把程序代码和被调用的函数代码链接起来，从而节省了内存资源。从上面的说明可以看出，DLL和.LIB文件必须随应用程序一起发行，否则应用程序将会产生错误。</p>
<p>静态库和共享库都是一个obj文件的集合 ，但静态链接后，执行程序中存在自己所需obj的一份拷贝，而动态链接后，执行程序仅仅是包含对共享库的一个引用。共享库相当于一个由多个obj文件组合而成的obj文件，在链接后其所有代码被加载，不管需要的还是不需要的。<br>似乎可以得出一个结论：<br>&nbsp; 静态链接后的程序比动态链接的所用存储空间大，因为执行程序中包含了库中代码拷贝；<br>&nbsp; 而动态链接的程序比静态链接的所用的运行空间大，因为它将不需要的代码也加载到运行空间。</p>
<p><br><span style="COLOR: red">针对上面的知识2 个问题：<br><br>1） DLL和.LIB文件必须随应用程序一起发行，否则应用程序将会产生错误。 <br>我的答案：lib应该不需要吧。<br><br>2）如果是某个程序中调用了一个动态库（通过header文件，lib+dll来调用），则对动态库的某个函数的内容修改了，但接口不改，则调用此动态库的程序需重新编译连接吗？如果是通过loadlibary动态加载，需要重新编译连接吗？<br>我的答案：通过header+lib+dll调用的话需要重新编译连接，但是通过loadlibrary来使用的话，不需要重新编译连接。<br><br>欢迎大家讨论！<br><br>完！</span></p><img src ="http://www.cppblog.com/mzty/aggbug/134901.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2010-11-28 17:12 <a href="http://www.cppblog.com/mzty/archive/2010/11/28/134901.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++强大的背后</title><link>http://www.cppblog.com/mzty/archive/2010/09/18/126964.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Sat, 18 Sep 2010 02:07:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2010/09/18/126964.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/126964.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2010/09/18/126964.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/126964.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/126964.html</trackback:ping><description><![CDATA[<br>转自：<a href="http://www.cnblogs.com/miloyip/archive/2010/09/17/1828449.html">http://www.cnblogs.com/miloyip/archive/2010/09/17/1828449.html</a><br><br>
<p>在31年前(1979年)，一名刚获得博士学位的研究员，为了开发一个软件项目发明了一门新编程语言，该研究员名为<a href="http://www2.research.att.com/~bs/"><font color=#3d81ee>Bjarne Stroustrup</font></a>，该门语言则命名为——C with classes，四年后改称为C++。C++是一门通用编程语言，支持多种编程范式，包括过程式、面向对象(object-oriented programming, OP)、泛型(generic programming, GP)，后来为泛型而设计的模版，被<a href="http://www.erwin-unruh.de/meta.html"><font color=#3d81ee>发现</font></a>及<a href="http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=AA022F3026015EF910CAEF5156901019?doi=10.1.1.14.3670&amp;rep=rep1&amp;type=pdf"><font color=#3d81ee>证明是图灵完备的</font></a>，因此使C++亦可支持<a href="http://en.wikipedia.org/wiki/Template_metaprogramming"><font color=#3d81ee>模版元编程范式(template metaprogramming, TMP)</font></a>。C++继承了C的特色，既为高级语言，又含低级语言功能，可同时作为系统和应用编程语言。</p>
<p>C++广泛应用在不同领域，使用者<a href="http://www2.research.att.com/~bs/bs_faq.html#number-of-C++-users"><font color=#3d81ee>以数百万计</font></a>。根据<a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"><font color=#3d81ee>近十年的调查</font></a>，C++的流行程度约稳定排行第3位(于C/Java之后)。 C++经历长期的实践和演化，才成为今日的样貌。1998年，C++标准委员会排除万难，使C++成为ISO标准(俗称C++98)，当中含非常强大的<a href="http://www.sgi.com/tech/stl/"><font color=#3d81ee>标准模版库(standard template library, STL)</font></a>。之后委员会在2005年提交了有关标准库的<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf"><font color=#3d81ee>第一个技术报告(简称TR1)</font></a>，并为下一个标准<a href="http://en.wikipedia.org/wiki/C%2B%2B0x"><font color=#3d81ee>C++0x</font></a>而努力。可惜C++0x并不能在200x年完成，各界希望新标准能于2011年内出台。</p>
<p>流行的C++编译器中，微软Visual C++ 2010已实现<a href="http://msdn.microsoft.com/en-us/library/dd465215.aspx"><font color=#3d81ee>部分C++0x语法并加入TR1扩充库</font></a>，而gcc对<a href="http://gcc.gnu.org/projects/cxx0x.html"><font color=#3d81ee>C++0x语法和库的支持</font></a>比VC2010更多。</p>
<h2>应否选择C++</h2>
<h3>哪些程序适宜使用C++?</h3>
<p>C++并非万能丹，我按经验举出一些C++的适用时机。</p>
<ul>
    <li>C++适合构造程序中需求较稳定的部分，需求变化较大的部分可使用脚本语言；</li>
    <li>程序须尽量发挥硬件的最高性能，且性能瓶颈在于CPU和内存；</li>
    <li>程序须频繁地与操作系统或硬件沟通；</li>
    <li>程序必须使用C++框架/库，如大部分游戏引擎(如Unreal/Source)及中间件(如Havok/FMOD)，虽然有些C++库提供其他语言的绑定，但通常原生的API性能最好、最新；</li>
    <li>项目中某个目标平台只提供C++编译器的支持。</li>
</ul>
<p>按应用领域来说，C++适用于开发服务器软件、桌面应用、游戏、实时系统、高性能计算、嵌入式系统等。</p>
<h3>使用C++还是C? </h3>
<p>C++和C的设计哲学并不一样，两者取舍不同，所以不同的程序员和软件项目会有不同选择，难以一概而论。与C++相比，C具备编译速度快、容易学习、显式描述程序细节、较少更新标准(后两者也可同时视为缺点)等优点。在语言层面上，C++包含绝大部分C语言的功能(例外之一，C++没有C99的<a href="http://en.wikipedia.org/wiki/Variable-length_array"><font color=#3d81ee>变长数组VLA</font></a>)，且提供OOP和GP的特性。但其实用C也可实现OOP思想，亦可利用宏去实现某程度的GP，只不过C++的语法能较简洁、自动地实现OOP/GP。C++的<a href="http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization"><font color=#3d81ee>RAII</font></a>(resource acquisition is initialization，资源获取就是初始化)特性比较独特，C/C#/Java没有相应功能。回顾历史，Stroustrup开发的早期C++编译器Cpre/<a href="http://en.wikipedia.org/wiki/Cfront"><font color=#3d81ee>Cfront</font></a>是把C++源代码翻译为C，再用C编译器编译的。由此可知，C++编写的程序，都能用等效的C程序代替，但C++在语言层面上提供了OOP/GP语法、更严格的类型检查系统、大量额外的语言特性(如异常、<a href="http://en.wikipedia.org/wiki/RTTI"><font color=#3d81ee>RTTI</font></a>等)，并且C++标准库也较丰富。有时候C++的语法可使程序更简洁，如运算符重载、隐式转换。但另一方面，C语言的API通常比C++简洁，能较容易供其他语言程序调用。因此，一些C++库会提供C的API封装，同时也可供C程序调用。相反，有时候也会把C的API封装成C++形式，以支持RAII和其他C++库整合等。 </p>
<h3>为何C++性能可优于其他语言?</h3>
<p>相对运行于虚拟机语言(如C#/Java)，C/C++直接以静态形式把源程序编译为目标平台的机器码。一般而言，C/C++程序在编译及链接时可进行的优化最丰富，启动时的速度最快，运行时的额外内存开销最少。而C/C++相对动态语言(如Python/Lua)也减少了运行时的动态类型检测。此外，C/C++的运行行为是确定的，且不会有额外行为(例如C#/Java必然会初始化变量)，也不会有如垃圾收集(GC)而造成的不确定性延迟，而且C/C++的数据结构在内存中的布局也是确定的。有时C++的一些功能会使程序性能优于C，当中以内联和模版最为突出，这两项功能使C++标准库的sort()通常比C标准库的qsort()<a href="http://en.wikipedia.org/wiki/Sort_(C%2B%2B)#Comparison_to_qsort.28.29"><font color=#3d81ee>快多倍</font></a>(C可用宏或人手编码去解决此问题)。另一方面，C/C++能直接映射机器码，之间没有另一层中间语言，因此可以做底层优化，例如使用<a href="http://en.wikipedia.org/wiki/Intrinsic_function"><font color=#3d81ee>内部(intrinsic)函数</font></a>和嵌入汇编语言。然而，许多C++的性能优点并非免费午餐，代价包括较长的编译链接时间和较易出错，因而增加开发时间和成本，这点稍后补充。</p>
<p>我进行了一个简单全局渲染性能测试(512x512像素，每像素10000个采样)，C++ 1小时36分、Java 3小时18分、Python约18天、Ruby约351天。评测方式和其他语言的结果详见<a href="http://www.cnblogs.com/miloyip/archive/2010/07/07/languages_brawl_GI.html"><font color=#3d81ee>博文</font></a>。</p>
<h2>C++常见问题</h2>
<h3>C++源代码跨平台吗?</h3>
<p>C++有不错的跨平台能力，但由于直接映射硬件，因性能优化的关系，跨平台能力不及Java及多数脚本语言。然而，实践跨平台的C++软件还是可行的，但须注意以下问题：</p>
<ul>
    <li>C++标准没有规定原始数据类型(如int)的大小，需要特定大小的类型时，可自订类型(如int32_t)，同时对任何类型使用sizeof()而不假设其大小；</li>
    <li>字节序(byte order)按CPU有所不同，特别要注意二进制输入输出、reinterpret_cast法；</li>
    <li>原始数据和结构类型的地址对齐有差异；</li>
    <li>编译器提供的一些编译器或平台专用扩充指令；</li>
    <li>避免作<a href="http://en.wikipedia.org/wiki/Application_binary_interface"><font color=#3d81ee>应用二进制接口(application binary interface, ABI)</font></a>的假设，例如调用函数时参数的取值顺序在C/C++中没定义，在C++中也不可随便假设RTTI/虚表等实现方式。</li>
</ul>
<p>总括而言，跨平台C++软件可在头文件中用宏检测编译器和平台，再用宏、typedef、自定平台相关实现等方法去实践跨平台，C++标准不会提供这类帮助。</p>
<h3>C++程序容易崩溃?</h3>
<p>和许多语言相比，C/C++提供不安全的功能以最优化性能，有可能造成崩溃。但要注意，很多运行时错误，如向空指针/引用解引用、数组越界、堆栈溢出等，其他语言也会报错或抛出异常，这些都是程序问题，而不是语言本身的问题。有些意见认为，出现这类运行时错误，应该尽量写入日志并立即崩溃，不该让程序继续运行，以免造成更大的影响(例如程序继续把内存中错误的数据覆写文件)。若要容错，可按业务把程序分割为多进程，像<a href="http://dev.chromium.org/developers/design-documents/multi-process-architecture"><font color=#3d81ee>Chrome</font></a>或使用fork()的形式。然而，C++有许多机制可以减少错误，例如以<a href="http://en.wikipedia.org/wiki/String_(C%2B%2B)"><font color=#3d81ee>string</font></a>代替C字符串；以<a href="http://en.wikipedia.org/wiki/Vector_(C%2B%2B)"><font color=#3d81ee>vector</font></a>或<a href="http://en.wikipedia.org/wiki/Array_(C%2B%2B)"><font color=#3d81ee>array(TR1)</font></a>代替原始数组(有些实现可在调试模式检测越界)；使用智能指针也能减少一些原始指针的问题。另外，我最常遇到的Bug，就是没有初始化成员变量，有时会导致崩溃，而且调试版和发行版的行为可能不同。</p>
<h3>C++要手动做内存管理?</h3>
<p>C++同时提供在堆栈上的自动局部变量，以及从自由存储(free store)分配的对象。对于后者，程序员需手动释放，或使用不同的容器和智能指针。 C++程序员经常进一步优化内存，自定义内存分配策略以提升效能，例如使用对象池、自定义的单向/双向堆栈区等。虽然C++0x还没加入GC功能，但也可以自行编写或使用现成库。此外，C/C++也可以直接使用操作系统提供的内存相关功能，例如内存映射文件、共享内存等。</p>
<h3>使用C++常要重造轮子?</h3>
<p>我曾参与的C++项目，都会重造不少标准库已提供的功能，此情况在其他语言中较少出现。我试图分析个中原因。首先，C++标准库相对很多语言来说是贫乏的，各开发者便会重复地制造自订库。从另一个角度看，C++标准库是用C++编写的(很多其他语言不用自身而是用C/C++去编写库)，在能力和性能上，自订库和标准库并无本质差别；另外，标准库为通用而设，对不同平台及多种使用需求作取舍，性能上有所影响，例如EA公司就曾发表自制的EASTL规格，描述游戏开发方面对STL的性能及功能需求的特点；此外，多个C++库一起使用，经常会因规范不同而引起冲突，又或功能重叠，所以项目可能须自行开发，或引入其他库的概念或实现(如<a href="http://www.boost.org/"><font color=#3d81ee>Boost</font></a>/<a href="http://en.wikipedia.org/wiki/C%2B%2B_Technical_Report_1"><font color=#3d81ee>TR1</font></a>/<a href="http://loki-lib.sourceforge.net/"><font color=#3d81ee>Loki</font></a>)，改写以符合项目规范。</p>
<h3>C++编译速度很慢?</h3>
<p>错，是非常慢。我认为C++可能是实用程序语言中编译速度最慢的。此问题涉及C++沿用C的编译链接方式，又加入了复杂的类/泛型声明和内联机制，使编译时间倍增。在C++对编译方法改革之前(如<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2073.pdf"><font color=#3d81ee>module提案</font></a>)，可使用以下技巧改善：第一，使用<a href="http://en.wikipedia.org/wiki/Opaque_pointer"><font color=#3d81ee>pimpl手法</font></a>，因性能损耗应用于调用次数不多的类；第二，仅包含必要头文件，并尽量使用及提供前置声明版本的头文件(如iosfwd)；第三采用基于接口的设计，但须注意虚函数调用成本；第四，采用<a href="http://buffered.io/2007/12/10/the-magic-of-unity-builds/"><font color=#3d81ee>unity build</font></a>，即把多个cpp文件结合在一个编译单元进行编译；第五，采用分布式生成系统如<a href="http://www.xoreax.com/"><font color=#3d81ee>IncrediBuild</font></a>。</p>
<h3>C++缺乏什么功能?</h3>
<p>虽然C++已经非常复杂，但仍缺少很多常见功能。 C++0x作出了不少改善，例如语言方面加入Lambda函数、闭包、类型推导声明等，而库方面则加入正则表达式、采用哈希表的unordered_set/unordered_map、引用计数智能指针shared_ptr/weak_ptr等。但最值得留意的是C++0x引入多线程的语法和库功能，这是C++演进的一大步。然而，模组、GC、反射机制等功能虽有提案，却未加进C++0x。</p>
<h2>C++使用建议</h2>
<h3>为应用挑选特性集</h3>
<p>我同意Stroustrup关于使用C++各种技术的回应：&#8220;你可以做，不意味着你必须这么做。(Just because you can do it, doesn't mean that you have to.)&#8221; C++充满丰富的特性，但同时带来不同问题，例如过分复杂、编译及运行性能的损耗。一般可考虑是否使用多重继承、异常、RTTI，并调节使用模版及模版元编程的程度。使用过分复杂的设计和功能，可能会令部分团队成员更难理解和维护。</p>
<h3>为团队建立编程规范</h3>
<p>C++的编码自由度很高，容易编写风格迥异的代码，C++本身也没有定义一些标准规范。而且，C++的源文件物理构成，较许多语言复杂。因此，除了决定特性集，每个团队应建立一套编程规范，包括源文件格式(可使用文件模版)、花括号风格。</p>
<h3>尽量使用C++风格而非C风格</h3>
<p>由于C++有对C兼容的包袱，一些功能可以使用C风格实现，但最好使用C++提供的新功能。最基本的是尽量以具名常量、内联函数和泛型取代宏，只把宏用在条件式编译及特殊情况。旧式的C要求局部变量声明在作用域开端，C++则无此限制，应把变量声明尽量置于邻近其使用的地方，for()的循环变量声明可置于for的括号内。 C++中能加强类型安全的功能应尽量使用，例如避免&#8220;万能&#8221;指针void *，而使用个别或泛型类型；用bool而非int表示布尔值；选用4种C++ cast关键字代替简单的强制转换。</p>
<h3>结合其他语言</h3>
<p>如前文所述，C++并非适合所有应用情境，有时可以混合其他语言使用，包括用C++扩展其他语言，或在C++程序中嵌入脚本语言引擎。对于后者，除了使用各种脚本语言的专门API，还可使用<a href="http://www.boost.org/doc/libs/1_42_0/libs/python/doc/index.html"><font color=#3d81ee>Boost</font></a>或<a href="http://www.swig.org/"><font color=#3d81ee>SWIG</font></a>作整合。</p>
<h2>C++学习建议</h2>
<p>C++缺点之一，是相对许多语言复杂，而且难学难精。许多人说学习C语言只需一本K&amp;R<a href="http://book.douban.com/subject/1139336/"><font color=#3d81ee>《C程序设计语言》</font></a>即可，但C++书籍却是多不胜数。我是从C进入C++，皆是靠阅读自学。在此分享一点学习心得。个人认为，学习C++可分为4个层次：</p>
<ul>
    <li>第一层次，C++基础：挑选一本入门书籍，如<a href="http://book.douban.com/subject/4262575/"><font color=#3d81ee>《C++ Primer》</font></a>、<a href="http://book.douban.com/subject/2030264/"><font color=#3d81ee>《C++大学教程》</font></a>、或Stroustrup撰写的经典<a href="http://book.douban.com/subject/1099889/"><font color=#3d81ee>《C++程序设计语言》</font></a>或他一年半前的新作<a href="http://book.douban.com/subject/4875599/"><font color=#3d81ee>《C++程序设计原理与实践》</font></a>，而一般C++课程也止于此，另外<a href="http://book.douban.com/subject/1110941/"><font color=#3d81ee>《C++ 标准程序库》</font></a>及<a href="http://book.douban.com/subject/1868179/"><font color=#3d81ee>《The C++ Standard Library Extensions》</font></a>可供参考；</li>
    <li>第二层次，正确高效地使用C++：此层次开始必须自修，阅读过《(<a href="http://book.douban.com/subject/1241385/"><font color=#3d81ee>More</font></a>)<a href="http://book.douban.com/subject/1842426/"><font color=#3d81ee>Effective C++</font></a>》、《(<a href="http://book.douban.com/subject/1244943/"><font color=#3d81ee>More</font></a>)<a href="http://book.douban.com/subject/1967356/"><font color=#3d81ee>Exceptional C++</font></a>》、<a href="http://book.douban.com/subject/1792179/"><font color=#3d81ee>《Effective STL》</font></a>及<a href="http://book.douban.com/subject/1480481/"><font color=#3d81ee>《C++编程规范》</font></a>等，才适宜踏入专业C++开发之路；</li>
    <li>第三层次，深入了解C++：关于全局问题可读<a href="http://book.douban.com/subject/1091086/"><font color=#3d81ee>《深入探索C++对象模型》</font></a>、<a href="http://book.douban.com/subject/1470838/"><font color=#3d81ee>《Imperfect C++》</font></a>、<a href="http://book.douban.com/subject/2970056/"><font color=#3d81ee>《C++沉思录》</font></a>、<a href="http://book.douban.com/subject/1110934/"><font color=#3d81ee>《STL源码剖析》</font></a>，要挑战智商，可看关于模版及模版元编程的书籍如<a href="http://book.douban.com/subject/2378124/"><font color=#3d81ee>《C++ Templates》</font></a>、<a href="http://book.douban.com/subject/1119904/"><font color=#3d81ee>《C++设计新思维》</font></a>、<a href="http://book.douban.com/subject/4136223/"><font color=#3d81ee>《C++模版元编程》</font></a>；</li>
    <li>第四层次，研究C++：阅读<a href="http://book.douban.com/subject/1096216/"><font color=#3d81ee>《C++语言的设计和演化》</font></a>、<a href="http://book.douban.com/subject/4722718/"><font color=#3d81ee>《编程的本质》</font></a>(含STL设计背后的数学根基)、C++标准文件<a href="http://openassist.googlecode.com/files/C%2B%2B%20Standard%20-%20ANSI%20ISO%20IEC%2014882%202003.pdf"><font color=#3d81ee>《ISO/IEC 14882:2003》</font></a>、<a href="http://www.open-std.org/JTC1/SC22/WG21/"><font color=#3d81ee>C++标准委员会</font></a>的提案书和报告书</a>、关于C++的学术文献。</li>
</ul>
<p>由于我主要是应用C++，大约只停留于第二、三个层次。然而，C++只是软件开发的一环而已，单凭语言并不能应付业务和工程上的问题。建议读者不要强求几年内&#8220;彻底学会C++的知识&#8221;，到达第二层左右便从工作实战中汲取经验，有兴趣才慢慢继续学习更高层次的知识。虽然学习C++有难度，但也是相当有趣且有满足感的。</p>
<p>数十年来，C++虽有起伏，但她依靠其使用者而不断得到顽强的生命力，相信在我退休之前都不会与她分离，也希望更进一步了解她，与她走进未来。</p>
<hr>
<p>本文原于<a href="http://www.programmer.com.cn/"><font color=#3d81ee>《程序员》</font></a>2010年8月刊揭载。</p><img src ="http://www.cppblog.com/mzty/aggbug/126964.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2010-09-18 10:07 <a href="http://www.cppblog.com/mzty/archive/2010/09/18/126964.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lnuix/Unix上C++开发使用啥工具</title><link>http://www.cppblog.com/mzty/archive/2010/04/15/112686.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Thu, 15 Apr 2010 09:08:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2010/04/15/112686.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/112686.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2010/04/15/112686.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/112686.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/112686.html</trackback:ping><description><![CDATA[<br><br><br>你在liunx/Unix使用啥工具来开发C++呢？（我是新手望多指教） <br><br><br>调查如下：<a href="http://www.askform.cn/68163-74318.aspx">http://www.askform.cn/68163-74318.aspx</a><br><br>结果：<br><img border=0 alt="" src="http://images.cnblogs.com/cnblogs_com/itech/246265/r_cide.png" width=504 height=408><br><br><br>2天后撤下首页！谢谢支持！ <br><br>完！<img src ="http://www.cppblog.com/mzty/aggbug/112686.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2010-04-15 17:08 <a href="http://www.cppblog.com/mzty/archive/2010/04/15/112686.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++对象模型</title><link>http://www.cppblog.com/mzty/archive/2009/03/03/75456.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Tue, 03 Mar 2009 12:55:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2009/03/03/75456.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/75456.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2009/03/03/75456.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/75456.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/75456.html</trackback:ping><description><![CDATA[<p>C++对象模型系列，探索C++对象的内存布局。具体看: <a target="_blank"  href="http://www.cnblogs.com/itech/archive/2009/02/19/1394268.html">http://www.cnblogs.com/itech/archive/2009/02/19/1394268.html</a></p>
<p><br></p><img src ="http://www.cppblog.com/mzty/aggbug/75456.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2009-03-03 20:55 <a href="http://www.cppblog.com/mzty/archive/2009/03/03/75456.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++的异常[转载]</title><link>http://www.cppblog.com/mzty/archive/2009/01/13/71848.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Tue, 13 Jan 2009 01:42:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2009/01/13/71848.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/71848.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2009/01/13/71848.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/71848.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/71848.html</trackback:ping><description><![CDATA[<p>转自：http://www.cnblogs.com/CUCmehp/archive/2009/01/12/1374320.html<br></p>
<p><br></p>
C++函数后面后加到关键字throw(something)限制，是对这个函数的异常安全性作出限制。<br><br>void f() throw()&nbsp; 表示f不允许抛出任何异常，即f是异常安全的。<br><br>void f() throw(...) 表示f可以抛出任何形式的异常。<br><br>void f() throw(exceptionType); 表示f只能抛出exceptionType类型的异常。<br><br>引别人的一个笑话：<br><br>throw() 大概会说：&#8220;噢，不管你抛什么，就是不准抛。。&#8221;<br>throw(...) 呵呵一笑，满脸慈祥：&#8220;抛吧抛吧，尽情地抛吧。。。&#8221;<br>throw(type) 一听急了：&#8220;那可不行，要抛也只能抛我的香烟头，否则要是不小心把俺祖传的金戒指抛掉就太亏了。。。&#8221;<br><br>关于C++的异常传递有三种方法：<br><br>1.传值(by value)<br><br>传值的过程中会产生临时对象的拷贝，不能解决多态的问题，如下：myexception继承exception，但是但确无法被正确的调用myexception的方法，造成对异常对象的切割。<br><br>class myexception:public exception{<br>
public:<br>
&nbsp;&nbsp;&nbsp; virtual const char* what() throw();<br>
};<br>
const char* myexception::what(){<br>
&nbsp;&nbsp;&nbsp; return "myException";<br>
}<br>
class A{<br>
public:<br>
&nbsp;&nbsp;&nbsp; A(){}<br>
&nbsp;&nbsp;&nbsp; void f() throw(){<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw myexception();<br>
&nbsp;&nbsp;&nbsp; }<br>
};<br>
int main(){<br>
&nbsp;&nbsp;&nbsp; A a;<br>
&nbsp;&nbsp;&nbsp; try{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a.f();<br>
&nbsp;&nbsp;&nbsp; }catch(exception exc){<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&lt;&lt;exc.what();<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br><br>运行结果：UnKnown exceptions<br><br>程序执行是会调用exception的what方法，而不是myexception的what方法。<br><br>2.传指针(by pointer)<br><br>指针可以实现多态，但往往会将临时对象的地址作为指针传出去，出现悬挂指针错误。如果在堆上分配内存空间，又往往不知道何时删除对象，出现to be or not to be的错误。<br><br>&nbsp; 结果显示：myException<br>Code<br>class myexception:public exception{<br>public:<br>&nbsp;&nbsp;&nbsp; virtual const char * what() const;<br>};<br>const char* myexception::what() const{<br>&nbsp;&nbsp;&nbsp; return "myException";<br>}<br>class A{<br>public:<br>&nbsp;&nbsp;&nbsp; A(){}<br>&nbsp;&nbsp;&nbsp; void f() throw(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new myexception();<br>&nbsp;&nbsp;&nbsp; }<br>};<br>int main(){<br>&nbsp;&nbsp;&nbsp; A a;<br>&nbsp;&nbsp;&nbsp; try{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a.f();<br>&nbsp;&nbsp;&nbsp; }catch(exception* pexc){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&lt;&lt;pexc-&gt;what();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete pexc;<br>&nbsp;&nbsp;&nbsp; }<br>}<br><br>&nbsp;<br><br>3.传引用(by reference)<br><br>传引用是最好的方法，可以克服前面的两个问题。<br><br>程序结果显示:myException<br><br>Code<br>class myexception:public exception{<br>public:<br>&nbsp;&nbsp;&nbsp; virtual const char * what() const;<br>};<br>const char* myexception::what() const{<br>&nbsp;&nbsp;&nbsp; return "myException";<br>}<br>class A{<br>public:<br>&nbsp;&nbsp;&nbsp; A(){}<br>&nbsp;&nbsp;&nbsp; void f() throw(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw myexception();<br>&nbsp;&nbsp;&nbsp; }<br>};<br>int main(){<br>&nbsp;&nbsp;&nbsp; A a;<br>&nbsp;&nbsp;&nbsp; try{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a.f();<br>&nbsp;&nbsp;&nbsp; }catch(exception&amp; exc){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&lt;&lt;exc.what();<br>&nbsp;&nbsp;&nbsp; }<br>}<img src ="http://www.cppblog.com/mzty/aggbug/71848.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2009-01-13 09:42 <a href="http://www.cppblog.com/mzty/archive/2009/01/13/71848.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《windows via C++》之windows线程同步</title><link>http://www.cppblog.com/mzty/archive/2008/07/29/57470.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Tue, 29 Jul 2008 14:54:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2008/07/29/57470.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/57470.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2008/07/29/57470.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/57470.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/57470.html</trackback:ping><description><![CDATA[<p><br>来自：梦在天涯C++博客(<a href="http://www.cppblog.com/mzty/">http://www.cppblog.com/mzty/</a>)</p>
<p>一 线程</p>
<p>1）如果你正在编写C/C++代码，决不应该调用CreateThread。相反，应该使用VisualC++运行期库函数_beginthreadex，退出也应该使用_endthreadex。如果不使用Microsoft的VisualC++编译器，你的编译器供应商有它自己的CreateThred替代函数。不管这个替代函数是什么，你都必须使用。</p>
<p><br>2）因为_beginthreadex和_endthreadex是CRT线程函数，所以必须注意编译选项runtimelibaray的选择，使用MT或MTD。</p>
<p>3) _beginthreadex函数的参数列表与CreateThread函数的参数列表是相同的，但是参数名和类型并不完全相同。这是因为Microsoft的C/C++运行期库的开发小组认为，C/C++运行期函数不应该对Windows数据类型有任何依赖。_beginthreadex函数也像CreateThread那样，返回新创建的线程的句柄。</p>
<p>4）下面是关于_beginthreadex的一些要点：</p>
<p>&#8226;每个线程均获得由C/C++运行期库的堆栈分配的自己的tiddata内存结构。（tiddata结构位于Mtdll.h文件中的VisualC++源代码中）。</p>
<p>&#8226;传递给_beginthreadex的线程函数的地址保存在tiddata内存块中。传递给该函数的参数也保存在该数据块中。</p>
<p>&#8226;_beginthreadex确实从内部调用CreateThread，因为这是操作系统了解如何创建新线程的唯一方法。</p>
<p>&#8226;当调用CreatetThread时，它被告知通过调用_threadstartex而不是pfnStartAddr来启动执行新线程。还有，传递给线程函数的参数是tiddata结构而不是pvParam的地址。</p>
<p>&#8226;如果一切顺利，就会像CreateThread那样返回线程句柄。如果任何操作失败了，便返回NULL。</p>
<p>5) _endthreadex的一些要点：</p>
<p>&#8226;C运行期库的_getptd函数内部调用操作系统的TlsGetValue函数，该函数负责检索调用线程的tiddata内存块的地址。</p>
<p>&#8226;然后该数据块被释放，而操作系统的ExitThread函数被调用，以便真正撤消该线程。当然，退出代码要正确地设置和传递。</p>
<p>6) 虽然也提供了简化版的的_beginthread和_endthread，但是可控制性太差，所以一般不使用。</p>
<p>6）线程handle因为是内核对象，所以需要在最后close handle。</p>
<p>7）C++主线程的终止，同时也会终止所有主线程创建的子线程，不管子线程有没有执行完毕。</p>
<p>8）如果某线程挂起，然后有调用WaitForSingleObject等待该线程，就会导致死锁。</p>
<p>二 线程同步之Critical Sections</p>
<p>1） 因为Critical Sections不是内核对象，所以只能用来同一进程内线程间的同步，不能用来多个不同进程间的线程的同步。</p>
<p>2） 如果在Critical Sections中间突然程序crash或是exit而没有调用LeaveCriticalSection，则结果是该线程所对应的内核不能被释放，该线程成为死线程。</p>
<p>3） 要比其他的内核对象的速度要快。</p>
<p>4）很好的封装：</p>
<p>class CritSect<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; friend class Lock;<br>&nbsp;&nbsp;&nbsp; CritSect() { InitializeCriticalSection(&amp;_critSection); }<br>&nbsp;&nbsp;&nbsp; ~CritSect() { DeleteCriticalSection(&amp;_critSection); }<br>private:<br>&nbsp;&nbsp;&nbsp; void Acquire(){EnterCriticalSection(&amp;_critSection);}<br>&nbsp;&nbsp;&nbsp; void Release(){LeaveCriticalSection(&amp;_critSection);}</p>
<p>&nbsp;&nbsp;&nbsp; CRITICAL_SECTION _critSection;<br>};</p>
<p>class Lock<br>{<br>public:<br>&nbsp;&nbsp;&nbsp;&nbsp; Lock(CritSect&amp; critSect):_critSect(critSect) {&nbsp;&nbsp;&nbsp; _critSect.Acquire(); }<br>&nbsp;&nbsp;&nbsp;&nbsp; ~Lock(){_critSect.Release();}<br>private:<br>&nbsp;&nbsp;&nbsp; CritSect&amp; _critSect;<br>};<br>调用：CritSect sect;Lock lock(sect);</p>
<p>三 线程同步之Mutex<br>&nbsp;&nbsp;&nbsp; <br>1）互斥对象（mutex）内核对象能够确保线程拥有对单个资源的互斥访问权。实际上互斥对象是因此而得名的。互斥对象包含一个使用数量，一个线程ID和一个递归计数器。<br>&nbsp;2） 互斥对象的行为特性与关键代码段相同，但是互斥对象属于内核对象，而关键代码段则属于用户方式对象。这意味着互斥对象的运行速度比关键代码段要慢。但是这也意味着不同进程中的多个线程能够访问单个互斥对象，并且这意味着线程在等待访问资源时可以设定一个超时值。</p>
<p>&nbsp;3） ID用于标识系统中的哪个线程当前拥有互斥对象，递归计数器用于指明该线程拥有互斥对象的次数。</p>
<p>&nbsp;4） 互斥对象有许多用途，属于最常用的内核对象之一。通常来说，它们用于保护由多个线程访问的内存块。如果多个线程要同时访问内存块，内存块中的数据就可能遭到破坏。互斥对象能够保证访问内存块的任何线程拥有对该内存块的独占访问权，这样就能够保证数据的完整性。</p>
<p>5）互斥对象的使用规则如下：</p>
<p>&#8226; 如果线程ID是0（这是个无效ID），互斥对象不被任何线程所拥有，并且发出该互斥对象的通知信号。</p>
<p>&#8226; 如果ID是个非0数字，那么一个线程就拥有互斥对象，并且不发出该互斥对象的通知信号。</p>
<p>&#8226; 与所有其他内核对象不同， 互斥对象在操作系统中拥有特殊的代码，允许它们违反正常的规则。</p>
<p><br>四 线程同步之Event</p>
<p>1）在所有的内核对象中，事件内核对象是个最基本的对象。它们包含一个使用计数（与所有内核对象一样），一个用于指明该事件是个自动重置的事件还是一个人工重置的事件的布尔值，另一个用于指明该事件处于已通知状态还是未通知状态的布尔值。 </p>
<p>2）事件能够通知一个操作已经完成。有两种不同类型的事件对象。一种是人工重置的事件，另一种是自动重置的事件。当人工重置的事件得到通知时，等待该事件的所有线程均变为可调度线程。当一个自动重置的事件得到通知时，等待该事件的线程中只有一个线程变为可调度线程。 </p>
<p>3）当一个线程执行初始化操作，然后通知另一个线程执行剩余的操作时，事件使用得最多。事件初始化为未通知状态，然后，当该线程完成它的初始化操作后，它就将事件设置为已通知状态。这时，一直在等待该事件的另一个线程发现该事件已经得到通知，因此它就变成可调度线程。</p>
<p>&nbsp;4）Microsoft为自动重置的事件定义了应该成功等待的副作用规则，即当线程成功地等待到该对象时，自动重置的事件就会自动重置到未通知状态。这就是自动重置的事件如何获得它们的名字的方法。通常没有必要为自动重置的事件调用ResetEvent函数，因为系统会自动对事件进行重置。但是，Microsoft没有为人工重置的事件定义成功等待的副作用，所以需要调用ResetEvent()。<br><br></p>
<p>五 线程同步之信号量（Semaphore）<br></p>
<p>信号量（Semaphore）内核对象对线程的同步方式与前面几种方法不同，它允许多个线程在同一时刻访问同一资源，但是需要限制在同一时刻访问此资源的最大线程数目。在用 CreateSemaphore（）创建信号量时即要同时指出允许的最大资源计数和当前可用资源计数。一般是将当前可用资源计数设置为最大资源计数，每增加一个线程对共享资源的访问，当前可用资源计数就会减1，只要当前可用资源计数是大于0的，就可以发出信号量信号。但是当前可用计数减小到0时则说明当前占用资源的线程数已经达到了所允许的最大数目，不能在允许其他线程的进入，此时的信号量信号将无法发出。线程在处理完共享资源后，应在离开的同时通过 ReleaseSemaphore（）函数将当前可用资源计数加1。在任何时候当前可用资源计数决不可能大于最大资源计数。</p>
<p>使用信号量内核对象进行线程同步主要会用到CreateSemaphore（）、OpenSemaphore（）、ReleaseSemaphore（）、 WaitForSingleObject（）和WaitForMultipleObjects（）等函数。<br><br>六 线程同步之其他</p>
<p>1）线程局部存储 （TLS），同一进程中的所有线程共享相同的虚拟地址空间。不同的线程中的局部变量有不同的副本，但是static和globl变量是同一进程中的所有线程共享的。使用TLS技术可以为static和globl的变量，根据当前进程的线程数量创建一个array，每个线程可以通过array的index来访问对应的变量，这样也就保证了static和global的变量为每一个线程都创建不同的副本。</p>
<p>2）互锁函数的家族十分的庞大，例如InterlockedExchangeAdd（）。。。，使用互锁函数的优点是：他的速度要比其他的CriticalSection,Mutex,Event,Semaphore快很多。</p>
<p>3）等待函数，例如WaitForSingleObject 函数用来检测 hHandle 事件的信号状态，当函数的执行时间超过 dwMilliseconds 就返回，但如果参数 dwMilliseconds 为 INFINITE 时函数将直到相应时间事件变成有信号状态才返回，否则就一直等待下去，直到 WaitForSingleObject 有返回直才执行后面的代码。</p>
<p>六 《Windows核心编程（英文版&#183;第5版）》<br>最好的windows多线程编程参考，更多更详细请看原书。</p><img src ="http://www.cppblog.com/mzty/aggbug/57470.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2008-07-29 22:54 <a href="http://www.cppblog.com/mzty/archive/2008/07/29/57470.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>dynamic_cast使用的讨论</title><link>http://www.cppblog.com/mzty/archive/2008/02/19/42929.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Tue, 19 Feb 2008 02:08:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2008/02/19/42929.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/42929.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2008/02/19/42929.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/42929.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/42929.html</trackback:ping><description><![CDATA[<br>一 问题<br>1）什么时候应必须使用dynamic_cast<br>2）什么时候dynamic_cast可以使用static_cast代替<br><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;TestCast.cpp&nbsp;:&nbsp;Defines&nbsp;the&nbsp;entry&nbsp;point&nbsp;for&nbsp;the&nbsp;console&nbsp;application.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></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">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</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">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: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Base<br><img id=Codehighlighter1_148_291_Open_Image onclick="this.style.display='none'; Codehighlighter1_148_291_Open_Text.style.display='none'; Codehighlighter1_148_291_Closed_Image.style.display='inline'; Codehighlighter1_148_291_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_148_291_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_148_291_Closed_Text.style.display='none'; Codehighlighter1_148_291_Open_Image.style.display='inline'; Codehighlighter1_148_291_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_148_291_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_148_291_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">public</span><span style="COLOR: #000000">:<br><img id=Codehighlighter1_180_209_Open_Image onclick="this.style.display='none'; Codehighlighter1_180_209_Open_Text.style.display='none'; Codehighlighter1_180_209_Closed_Image.style.display='inline'; Codehighlighter1_180_209_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_180_209_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_180_209_Closed_Text.style.display='none'; Codehighlighter1_180_209_Open_Image.style.display='inline'; Codehighlighter1_180_209_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.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;f()&nbsp;</span><span id=Codehighlighter1_180_209_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_180_209_Open_Text><span style="COLOR: #000000">{&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">Base::f</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;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_224_252_Open_Image onclick="this.style.display='none'; Codehighlighter1_224_252_Open_Text.style.display='none'; Codehighlighter1_224_252_Closed_Image.style.display='inline'; Codehighlighter1_224_252_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_224_252_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_224_252_Closed_Text.style.display='none'; Codehighlighter1_224_252_Open_Image.style.display='inline'; Codehighlighter1_224_252_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;f1()</span><span id=Codehighlighter1_224_252_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_224_252_Open_Text><span style="COLOR: #000000">{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">Base::f1</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;}</span></span><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;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;x;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;y;<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><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Derived&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Base<br><img id=Codehighlighter1_322_461_Open_Image onclick="this.style.display='none'; Codehighlighter1_322_461_Open_Text.style.display='none'; Codehighlighter1_322_461_Closed_Image.style.display='inline'; Codehighlighter1_322_461_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_322_461_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_322_461_Closed_Text.style.display='none'; Codehighlighter1_322_461_Open_Image.style.display='inline'; Codehighlighter1_322_461_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_322_461_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_322_461_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 id=Codehighlighter1_352_383_Open_Image onclick="this.style.display='none'; Codehighlighter1_352_383_Open_Text.style.display='none'; Codehighlighter1_352_383_Closed_Image.style.display='inline'; Codehighlighter1_352_383_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_352_383_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_352_383_Closed_Text.style.display='none'; Codehighlighter1_352_383_Open_Image.style.display='inline'; Codehighlighter1_352_383_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.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;f()</span><span id=Codehighlighter1_352_383_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_352_383_Open_Text><span style="COLOR: #000000">{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">Derived::f</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;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_405_436_Open_Image onclick="this.style.display='none'; Codehighlighter1_405_436_Open_Text.style.display='none'; Codehighlighter1_405_436_Closed_Image.style.display='inline'; Codehighlighter1_405_436_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_405_436_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_405_436_Closed_Text.style.display='none'; Codehighlighter1_405_436_Open_Image.style.display='inline'; Codehighlighter1_405_436_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.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;k()</span><span id=Codehighlighter1_405_436_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_405_436_Open_Text><span style="COLOR: #000000">{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">Derived::k</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;&nbsp;}</span></span><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;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;z;<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;Base1<br><img id=Codehighlighter1_477_582_Open_Image onclick="this.style.display='none'; Codehighlighter1_477_582_Open_Text.style.display='none'; Codehighlighter1_477_582_Closed_Image.style.display='inline'; Codehighlighter1_477_582_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_477_582_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_477_582_Closed_Text.style.display='none'; Codehighlighter1_477_582_Open_Image.style.display='inline'; Codehighlighter1_477_582_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_477_582_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_477_582_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 id=Codehighlighter1_507_536_Open_Image onclick="this.style.display='none'; Codehighlighter1_507_536_Open_Text.style.display='none'; Codehighlighter1_507_536_Closed_Image.style.display='inline'; Codehighlighter1_507_536_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_507_536_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_507_536_Closed_Text.style.display='none'; Codehighlighter1_507_536_Open_Image.style.display='inline'; Codehighlighter1_507_536_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.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;g()</span><span id=Codehighlighter1_507_536_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_507_536_Open_Text><span style="COLOR: #000000">{&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">Base1::g</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;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_551_580_Open_Image onclick="this.style.display='none'; Codehighlighter1_551_580_Open_Text.style.display='none'; Codehighlighter1_551_580_Closed_Image.style.display='inline'; Codehighlighter1_551_580_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_551_580_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_551_580_Closed_Text.style.display='none'; Codehighlighter1_551_580_Open_Image.style.display='inline'; Codehighlighter1_551_580_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;g1()</span><span id=Codehighlighter1_551_580_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_551_580_Open_Text><span style="COLOR: #000000">{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">Base1::g1</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;}</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></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Derived1&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Base,</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Base1<br><img id=Codehighlighter1_627_745_Open_Image onclick="this.style.display='none'; Codehighlighter1_627_745_Open_Text.style.display='none'; Codehighlighter1_627_745_Closed_Image.style.display='inline'; Codehighlighter1_627_745_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_627_745_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_627_745_Closed_Text.style.display='none'; Codehighlighter1_627_745_Open_Image.style.display='inline'; Codehighlighter1_627_745_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_627_745_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_627_745_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 id=Codehighlighter1_657_689_Open_Image onclick="this.style.display='none'; Codehighlighter1_657_689_Open_Text.style.display='none'; Codehighlighter1_657_689_Closed_Image.style.display='inline'; Codehighlighter1_657_689_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_657_689_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_657_689_Closed_Text.style.display='none'; Codehighlighter1_657_689_Open_Image.style.display='inline'; Codehighlighter1_657_689_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.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;f()</span><span id=Codehighlighter1_657_689_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_657_689_Open_Text><span style="COLOR: #000000">{&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">Derived1::f</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;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_711_743_Open_Image onclick="this.style.display='none'; Codehighlighter1_711_743_Open_Text.style.display='none'; Codehighlighter1_711_743_Closed_Image.style.display='inline'; Codehighlighter1_711_743_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_711_743_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_711_743_Closed_Text.style.display='none'; Codehighlighter1_711_743_Open_Image.style.display='inline'; Codehighlighter1_711_743_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.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;h()</span><span id=Codehighlighter1_711_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_711_743_Open_Text><span style="COLOR: #000000">{&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">Derived1::h</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;}</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;Test1()<br><img id=Codehighlighter1_762_1407_Open_Image onclick="this.style.display='none'; Codehighlighter1_762_1407_Open_Text.style.display='none'; Codehighlighter1_762_1407_Closed_Image.style.display='inline'; Codehighlighter1_762_1407_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_762_1407_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_762_1407_Closed_Text.style.display='none'; Codehighlighter1_762_1407_Open_Image.style.display='inline'; Codehighlighter1_762_1407_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_762_1407_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_762_1407_Open_Text><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;对于单继承，<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;如果PD真的指向Derived，用dynamic_cast和static_cast效果相同</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;Base&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pD&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Derived;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Derived&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pD1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dynamic_cast</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Derived</span><span style="COLOR: #000000">*&gt;</span><span style="COLOR: #000000">(pD);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pD1</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">f();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pD1</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">k();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pD1</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">f1();<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;Derived&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pD2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;static_cast</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Derived</span><span style="COLOR: #000000">*&gt;</span><span style="COLOR: #000000">(pD);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pD2</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">f();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pD2</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">k();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pD2</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">f1();<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><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;但是如果PB不是真的指向Derived，则用dynamic_cast则返回NULL，能够更早的禁止error的发生，<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;如果用static_cast虽然返回的不为NULL，但是运行时可能抛出exception。</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_1165_1181_Open_Image onclick="this.style.display='none'; Codehighlighter1_1165_1181_Open_Text.style.display='none'; Codehighlighter1_1165_1181_Closed_Image.style.display='inline'; Codehighlighter1_1165_1181_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1165_1181_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1165_1181_Closed_Text.style.display='none'; Codehighlighter1_1165_1181_Open_Image.style.display='inline'; Codehighlighter1_1165_1181_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 id=Codehighlighter1_1165_1181_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">/**/</span><span id=Codehighlighter1_1165_1181_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000">/&nbsp;Error&nbsp;code&nbsp;</span><span style="COLOR: #808080"></span></span><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">Base&nbsp;*pB&nbsp;=&nbsp;new&nbsp;Base();<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">Derived&nbsp;*pD3&nbsp;=&nbsp;static_cast&lt;Derived*&gt;(pB);<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">pD3-&gt;f();<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">pD3-&gt;k();<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">pD3-&gt;f1();<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">Derived&nbsp;*pD4&nbsp;=&nbsp;dynamic_cast&lt;Derived*&gt;(pB);<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">pD4-&gt;f();<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">pD4-&gt;k();<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">pD4-&gt;f1();</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><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></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Test2()<br><img id=Codehighlighter1_1423_2017_Open_Image onclick="this.style.display='none'; Codehighlighter1_1423_2017_Open_Text.style.display='none'; Codehighlighter1_1423_2017_Closed_Image.style.display='inline'; Codehighlighter1_1423_2017_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_1423_2017_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1423_2017_Closed_Text.style.display='none'; Codehighlighter1_1423_2017_Open_Image.style.display='inline'; Codehighlighter1_1423_2017_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_1423_2017_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_1423_2017_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: #008000">//</span><span style="COLOR: #008000">&nbsp;对于多重继承，<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;如果PD真的指向的是Derived1，使用dynamic_cast和static_cast都可以转化为Derived1，<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;但是如果要转化为Base的兄弟类Base1，必须使用dynamic_cast，使用static_cast不能编译。</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;Base&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pD&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Derived1;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Derived1&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pD1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dynamic_cast</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Derived1</span><span style="COLOR: #000000">*&gt;</span><span style="COLOR: #000000">(pD);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pD1</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">f();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pD1</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">h();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pD1</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">f1();<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;Base1&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pB1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dynamic_cast</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Base1</span><span style="COLOR: #000000">*&gt;</span><span style="COLOR: #000000">(pD);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pB1</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">g();<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;Derived1&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pD2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;static_cast</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Derived1</span><span style="COLOR: #000000">*&gt;</span><span style="COLOR: #000000">(pD);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pD2</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">f();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pD1</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">h();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pD2</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">f1();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_1849_1876_Open_Image onclick="this.style.display='none'; Codehighlighter1_1849_1876_Open_Text.style.display='none'; Codehighlighter1_1849_1876_Closed_Image.style.display='inline'; Codehighlighter1_1849_1876_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1849_1876_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1849_1876_Closed_Text.style.display='none'; Codehighlighter1_1849_1876_Open_Image.style.display='inline'; Codehighlighter1_1849_1876_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1849_1876_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">/**/</span><span id=Codehighlighter1_1849_1876_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000">/&nbsp;error&nbsp;can&nbsp;not&nbsp;compiler</span><span style="COLOR: #808080"></span></span><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">Base1&nbsp;*pB2&nbsp;=&nbsp;static_cast&lt;Base1*&gt;(pD);<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">pB2-&gt;g();<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;当然对于PB不是真的指向Derived1，想要转化为Derived1或Base的兄弟类Base1，情况与Test1中的error情况相同。</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></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/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;_tmain(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;_TCHAR</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br><img id=Codehighlighter1_2057_2098_Open_Image onclick="this.style.display='none'; Codehighlighter1_2057_2098_Open_Text.style.display='none'; Codehighlighter1_2057_2098_Closed_Image.style.display='inline'; Codehighlighter1_2057_2098_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_2057_2098_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_2057_2098_Closed_Text.style.display='none'; Codehighlighter1_2057_2098_Open_Image.style.display='inline'; Codehighlighter1_2057_2098_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_2057_2098_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_2057_2098_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Test1();<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;Test2();<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: #0000ff">return</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/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></div>
<br>三 结论<br><br>大家先总结下，哈哈！<img src ="http://www.cppblog.com/mzty/aggbug/42929.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2008-02-19 10:08 <a href="http://www.cppblog.com/mzty/archive/2008/02/19/42929.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 虚函数表解析（转）</title><link>http://www.cppblog.com/mzty/archive/2008/02/18/42877.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Mon, 18 Feb 2008 05:29:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2008/02/18/42877.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/42877.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2008/02/18/42877.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/42877.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/42877.html</trackback:ping><description><![CDATA[<p align=center><strong><span twffan="done">C++ <span twffan="done">虚函数表解析</span></span></strong></p>
<p align=center><font face="Times New Roman" size=3></font>&nbsp;</p>
<h1><span twffan="done"><font size=5>前言</font></span><font face="Times New Roman" size=3>&nbsp;</font></h1>
<p><font size=3><font face="Times New Roman">C++</font><span twffan="done">中的虚函数的作用主要是实现了多态的机制。关于多态，简而言之就是用父类型别的指针指向其子类的实例，然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有&#8220;多种形态&#8221;，这是一种泛型技术。所谓泛型技术，说白了就是试图使用不变的代码来实现可变的算法。比如：模板技术，</span><font face="Times New Roman">RTTI</font><span twffan="done">技术，虚函数技术，要么是试图做到在编译时决议，要么试图做到运行时决议。</span></font><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font size=3><span twffan="done">关于虚函数的使用方法，我在这里不做过多的阐述。大家可以看看相关的</span><font face="Times New Roman">C++</font><span twffan="done">的书籍。在这篇文章中，我只想从虚函数的实现机制上面为大家</span><span twffan="done"><font face="Times New Roman"> </font></span><span twffan="done">一个清晰的剖析。</span></font><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><font size=3>当然，相同的文章在网上也出现过一些了，但我总感觉这些文章不是很容易阅读，大段大段的代码，没有图片，没有详细的说明，没有比较，没有举一反三。不利于学习和阅读，所以这是我想写下这篇文章的原因。也希望大家多给我提意见。</font></span><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><font size=3>言归正传，让我们一起进入虚函数的世界。</font></span><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<h1><span twffan="done"><font size=5>虚函数表</font></span><font face="Times New Roman" size=3>&nbsp;</font></h1>
<p><font size=3><span twffan="done">对</span><font face="Times New Roman">C++ </font><span twffan="done">了解的人都应该知道虚函数（</span><font face="Times New Roman">Virtual Function</font><span twffan="done">）是通过一张虚函数表（</span><font face="Times New Roman">Virtual Table</font><span twffan="done">）来实现的。简称为</span><font face="Times New Roman">V-Table</font><span twffan="done">。在这个表中，主是要一个类的虚函数的地址表，这张表解决了继承、重载的问题，保证其容真实反应实际的函数。这样，在有虚函数的类的实例中这个表被分配在了这个实例的内存中，所以，当我们用父类的指针来操作一个子类的时候，这张虚函数表就显得由为重要了，它就像一个地图一样，指明了实际所应该调用的函数。</span></font><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font size=3><span twffan="done">这里我们着重看一下这张虚函数表。在</span><font face="Times New Roman">C++</font><span twffan="done">的标准规格说明书中说到，编译器必需要保证虚函数表的指针存在于对象实例中最前面的位置（这是为了保证正确取到虚函数的偏移量）。</span><span twffan="done"><font face="Times New Roman"> </font></span><span twffan="done">这意味着我们通过对象实例的地址得到这张虚函数表，然后就可以遍历其中函数指针，并调用相应的函数。</span></font><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font size=3><span twffan="done">听我扯了那么多，我可以感觉出来你现在可能比以前更加晕头转向了。</span><span twffan="done"><font face="Times New Roman"> </font></span><span twffan="done">没关系，下面就是实际的例子，相信聪明的你一看就明白了。</span></font><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><font size=3>假设我们有这样的一个类：</font></span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done">class</span><span twffan="done"> Base {</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp; </span>public</span><span twffan="done">:</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">virtual</span> <span twffan="done">void</span> f() { cout &lt;&lt; <span twffan="done">"Base::f"</span> &lt;&lt; endl; }</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">virtual</span> <span twffan="done">void</span> g() { cout &lt;&lt; <span twffan="done">"Base::g"</span> &lt;&lt; endl; }</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">virtual</span> <span twffan="done">void</span> h() { cout &lt;&lt; <span twffan="done">"Base::h"</span> &lt;&lt; endl; }</span>&nbsp;</p>
<p><span twffan="done">};</span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font size=3><span twffan="done">按照上面的说法，我们可以通过</span><font face="Times New Roman">Base</font><span twffan="done">的实例来得到虚函数表。</span><span twffan="done"><font face="Times New Roman"> </font></span><span twffan="done">下面是实际例程：</span></font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><span twffan="done"><font size=3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span><span twffan="done">typedef</span><span twffan="done"> <span twffan="done">void</span>(*Fun)(<span twffan="done">void</span>);</span><span twffan="done"><font size=3>&nbsp;</font></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Base b;</span>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Fun pFun = NULL;</span>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>cout &lt;&lt; <span twffan="done">"</span></span><span twffan="done">虚函数表地址：</span><span twffan="done">"</span><span twffan="done"> &lt;&lt; (<span twffan="done">int</span>*)(&amp;b) &lt;&lt; endl;</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>cout &lt;&lt; <span twffan="done">"</span></span><span twffan="done">虚函数表</span><span twffan="done"> — </span><span twffan="done">第一个函数地址：</span><span twffan="done">"</span><span twffan="done"> &lt;&lt; (<span twffan="done">int</span>*)*(<span twffan="done">int</span>*)(&amp;b) &lt;&lt; endl;<br></span>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">// Invoke the first virtual function&nbsp;</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun = (Fun)*((<span twffan="done">int</span>*)*(<span twffan="done">int</span>*)(&amp;b));</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun();</span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font size=3><span twffan="done">实际运行经果如下：</span><font face="Times New Roman">(Windows XP+VS2003,&nbsp;Linux 2.6.22 + GCC 4.1.3)</font></font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done">虚函数表地址：</span><span twffan="done">0012FED4</span></p>
<p><span twffan="done">虚函数表</span><span twffan="done"> — </span><span twffan="done">第一个函数地址：</span><span twffan="done">0044F148</span></p>
<p><span twffan="done">Base::f</span>&nbsp;</p>
<p><font size=3><span twffan="done">通过这个示例，我们可以看到，我们可以通过强行把</span><font face="Times New Roman">&amp;b</font><span twffan="done">转成</span><font face="Times New Roman">int *</font><span twffan="done">，取得虚函数表的地址，然后，再次取址就可以得到第一个虚函数的地址了，也就是</span><font face="Times New Roman">Base::f()</font><span twffan="done">，这在上面的程序中得到了验证（把</span><font face="Times New Roman">int* </font><span twffan="done">强制转成了函数指针）。通过这个示例，我们就可以知道如果要调用</span><font face="Times New Roman">Base::g()</font><span twffan="done">和</span><font face="Times New Roman">Base::h()</font><span twffan="done">，其代码如下：</span></font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><font face="Times New Roman" size=3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span><span twffan="done">(Fun)*((<span twffan="done">int</span>*)*(<span twffan="done">int</span>*)(&amp;b)+0);&nbsp;<span twffan="done">// Base::f()</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(Fun)*((<span twffan="done">int</span>*)*(<span twffan="done">int</span>*)(&amp;b)+1);&nbsp;<span twffan="done">// Base::g()</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(Fun)*((<span twffan="done">int</span>*)*(<span twffan="done">int</span>*)(&amp;b)+2);&nbsp;<span twffan="done">// Base::h()</span></span></p>
<p>&nbsp;</p>
<p><span twffan="done"><font size=3>这个时候你应该懂了吧。什么？还是有点晕。也是，这样的代码看着太乱了。没问题，让我画个图解释一下。如下所示：</font></span></p>
<p><span twffan="done"><font size=3></font></span></p>
<p align=center><span twffan="done"><font size=3><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_vtable1.jpg" twffan="done"></font></span></p>
<p><span twffan="done"><font size=3></font></span></p>
<p align=center><font size=3></font></p>
<p><font size=3><span twffan="done">注意：在上面这个图中，我在虚函数表的最后多加了一个结点，这是虚函数表的结束结点，就像字符串的结束符&#8220;</span><font face="Times New Roman">\0</font><span twffan="done">&#8221;一样，其标志了虚函数表的结束。这个结束标志的值在不同的编译器下是不同的。在</span><font face="Times New Roman">WinXP+VS2003</font><span twffan="done">下，这个值是</span><font face="Times New Roman">NULL</font><span twffan="done">。而在</span><font face="Times New Roman">Ubuntu 7.10 + Linux 2.6.22 + GCC 4.1.3</font><span twffan="done">下，这个值是如果</span><font face="Times New Roman">1</font><span twffan="done">，表示还有下一个虚函数表，如果值是</span><font face="Times New Roman">0</font><span twffan="done">，表示是最后一个虚函数表。</span></font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><font size=3>下面，我将分别说明&#8220;无重载&#8221;和&#8220;有重载&#8221;时的虚函数表的样子。没有重载父类的虚函数是毫无意义的。我之所以要讲述没有重载的情况，主要目的是为了给一个对比。在比较之下，我们可以更加清楚地知道其内部的具体实现。</font></span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<h1><span twffan="done"><font size=5>一般继承（无虚函数重载）</font></span></h1>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><font size=3>下面，再让我们来看看继承时的虚函数表是什么样的。假设有如下所示的一个继承关系：</font></span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p align=center><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_Drawing3.jpg" twffan="done"></p>
<p align=center><font face="Times New Roman" size=3></font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><font size=3>请注意，在这个继承关系中，子类没有重载任何父类的函数。那么，在派生类的实例中，其虚函数表如下所示：</font></span></p>
<p><span twffan="done"><font size=3></font></span></p>
<p align=center></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font size=3><span twffan="done">对于实例：</span><font face="Times New Roman">Derive d; </font><span twffan="done">的虚函数表如下：</span></font></p>
<p><font size=3></font></p>
<p align=center><font size=3><span twffan="done"><span twffan="done"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_vtable2.JPG" twffan="done"></span></span></font></p>
<p align=center><font size=3></font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><font size=3>我们可以看到下面几点：</font></span></p>
<p><font size=3><span twffan="done"><span twffan="done"><font face="Times New Roman">1）</font></span></span><span twffan="done">虚函数按照其声明顺序放于表中。</span></font></p>
<p><font size=3><span twffan="done"><span twffan="done"><font face="Times New Roman">2）</font></span></span><span twffan="done">父类的虚函数在子类的虚函数前面。</span></font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><font size=3>我相信聪明的你一定可以参考前面的那个程序，来编写一段程序来验证。</font></span><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<h1><span twffan="done"><font size=5>一般继承（有虚函数重载）</font></span></h1>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><font size=3>重载父类的虚函数是很显然的事情，不然，虚函数就变得毫无意义。下面，我们来看一下，如果子类中有虚函数重载了父类的虚函数，会是一个什么样子？假设，我们有下面这样的一个继承关系。</font></span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p align=center><font face="Times New Roman" size=3>&nbsp;<img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_Drawing4.jpg" twffan="done"></font></p>
<p align=center><font face="Times New Roman" size=3></font></p>
<p align=center><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font size=3><span twffan="done">为了让大家看到被继承过后的效果，在这个类的设计中，我只重载了父类的一个函数：</span><font face="Times New Roman">f()</font><span twffan="done">。那么，对于派生类的实例，其虚函数表会是下面的一个样子：</span></font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p align=center><font face="Times New Roman" size=3></font></p>
<p align=center><font face="Times New Roman" size=3><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_vtable3.JPG" twffan="done"></font></p>
<p>&nbsp;</p>
<p><font face="Times New Roman" size=3></font></p>
<p><span twffan="done"><font size=3>我们从表中可以看到下面几点，</font></span></p>
<p><font size=3><span twffan="done"><span twffan="done"><font face="Times New Roman">1）</font></span></span><span twffan="done">重载的</span><font face="Times New Roman">f()</font><span twffan="done">函数被放到了虚表中原来父类虚函数的位置。</span></font></p>
<p><font size=3><span twffan="done"><span twffan="done"><font face="Times New Roman">2）</font></span></span><span twffan="done">没有被重载的函数依旧。</span></font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><font size=3>这样，我们就可以看到对于下面这样的程序，</font></span></p>
<p><span twffan="done"><font size=3>&nbsp;</font></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Base *b = <span twffan="done">new</span> Derive();</span></p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>b-&gt;f();</span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font size=3><span twffan="done">由</span><font face="Times New Roman">b</font><span twffan="done">所指的内存中的虚函数表的</span><font face="Times New Roman">f()</font><span twffan="done">的位置已经被</span><font face="Times New Roman">Derive::f()</font><span twffan="done">函数地址所取代，于是在实际调用发生时，是</span><font face="Times New Roman">Derive::f()</font><span twffan="done">被调用了。这就实现了多态。</span></font><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<h1><span twffan="done"><font size=5>多重继承（无虚函数重载）</font></span><font face="Times New Roman" size=3>&nbsp;</font></h1>
<p><span twffan="done"><font size=3>下面，再让我们来看看多重继承中的情况，假设有下面这样一个类的继承关系。注意：子类并没有重载复类的函数。</font></span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p align=center><font face="Times New Roman" size=3></font></p>
<p align=center><font face="Times New Roman" size=3><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_Drawing1.jpg" twffan="done">&nbsp;</font></p>
<p align=center><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><font size=3>对于子类实例中的虚函数表，是下面这个样子：</font></span></p>
<p><span twffan="done"><font size=3></font></span></p>
<p align=center><span twffan="done"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_vtable4.JPG" twffan="done"></span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p align=center><font face="Times New Roman" size=3></font></p>
<p><span twffan="done"><font size=3>我们可以看到：</font></span></p>
<p><span twffan="done"><span twffan="done"><font face="Times New Roman"><font size=3>1）</font>&nbsp;</font></span></span><span twffan="done"><font size=3>每个父类都有自己的虚表。</font></span></p>
<p><span twffan="done"><span twffan="done"><font face="Times New Roman"><font size=3>2）</font>&nbsp;</font></span></span><span twffan="done"><font size=3>子类的成员函数被放到了第一个父类的表中。（所谓的第一个父类是按照声明顺序来判断的）</font></span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><font size=3>这样做就是为了解决不同的父类类型的指针指向同一个子类实例，而能够调用到实际的函数。</font></span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font><font face="Times New Roman" size=3>&nbsp;</font></p>
<h1><span twffan="done"><font size=5>多重继承（有虚函数重载）</font></span></h1>
<p><span twffan="done"><font size=3>下面我们再来看看，如果发生虚函数重载的情况。</font></span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font size=3><span twffan="done">下图中，我们重载了父类的</span><font face="Times New Roman">f()</font><span twffan="done">函数。</span></font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p align=center><font face="Times New Roman" size=3></font></p>
<p align=center><font face="Times New Roman" size=3><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_Drawing2.jpg" twffan="done">&nbsp;</font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><font size=3>下面是对于子类实例中的虚函数表的图：</font></span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p align=center><font face="Times New Roman" size=3></font></p>
<p align=center><font face="Times New Roman" size=3><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_vtable5.jpg" twffan="done"></font></p>
<p align=center>&nbsp;</p>
<p><font size=3><span twffan="done">我们可以看见，三个父类虚函数表中的</span><font face="Times New Roman">f()</font><span twffan="done">的位置被替换成了子类的函数指针。这样，我们就可以任一静态类型的父类来指向子类，并调用子类的</span><font face="Times New Roman">f()</font><span twffan="done">了。如：</span></font></p>
<p><span twffan="done"><font size=3>&nbsp;</font></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Derive d;</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Base1 *b1 = &amp;d;</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Base2 *b2 = &amp;d;</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Base3 *b3 = &amp;d;</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>b1-&gt;f(); <span twffan="done">//Derive::f()</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>b2-&gt;f(); <span twffan="done">//Derive::f()</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>b3-&gt;f(); <span twffan="done">//Derive::f()</span></span></p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>b1-&gt;g(); <span twffan="done">//Base1::g()</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>b2-&gt;g(); <span twffan="done">//Base2::g()</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>b3-&gt;g(); <span twffan="done">//Base3::g()</span></span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<h1><span twffan="done"><font size=5>安全性</font></span><font face="Times New Roman" size=3>&nbsp;</font></h1>
<p><font size=3><span twffan="done">每次写</span><font face="Times New Roman">C++</font><span twffan="done">的文章，总免不了要批判一下</span><font face="Times New Roman">C++</font><span twffan="done">。这篇文章也不例外。通过上面的讲述，相信我们对虚函数表有一个比较细致的了解了。水可载舟，亦可覆舟。下面，让我们来看看我们可以用虚函数表来干点什么坏事吧。</span></font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><strong><font size=3><span twffan="done">一、通过父类型的指针访问子类自己的虚函数</span></font></strong></p>
<p><font size=3><span twffan="done">我们知道，子类没有重载父类的虚函数是一件毫无意义的事情。因为多态也是要基于函数重载的。虽然在上面的图中我们可以看到</span><font face="Times New Roman">Base1</font><span twffan="done">的虚表中有</span><font face="Times New Roman">Derive</font><span twffan="done">的虚函数，但我们根本不可能使用下面的语句来调用子类的自有虚函数：</span></font></p>
<p><span twffan="done"><font size=3>&nbsp;</font></span></p>
<p><span twffan="done"><span twffan="done"><font size=3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span><span twffan="done">Base1 *b1 = <span twffan="done">new</span> Derive();</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>b1-&gt;f1();&nbsp;</span><span twffan="done">//<span twffan="done">编译出错</span></span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font size=3><span twffan="done">任何妄图使用父类指针想调用子类中的<strong>未重载父类的成员函数</strong>的行为都会被编译器视为非法，所以，这样的程序根本无法编译通过。但在运行时，我们可以通过指针的方式访问虚函数表来达到违反</span><font face="Times New Roman">C++</font><span twffan="done">语义的行为。（关于这方面的尝试，通过阅读后面附录的代码，相信你可以做到这一点）</span></font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font size=3><strong><span twffan="done">二、访问</span><font face="Times New Roman">non-public</font></strong><strong><span twffan="done">的虚函数</span></strong></font></p>
<p><font size=3><span twffan="done">另外，如果父类的虚函数是</span><font face="Times New Roman">private</font><span twffan="done">或是</span><font face="Times New Roman">protected</font><span twffan="done">的，但这些非</span><font face="Times New Roman">public</font><span twffan="done">的虚函数同样会存在于虚函数表中，所以，我们同样可以使用访问虚函数表的方式来访问这些</span><font face="Times New Roman">non-public</font><span twffan="done">的虚函数，这是很容易做到的。</span></font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done"><font size=3>如：</font></span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done">class</span><span twffan="done"> Base {</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp; </span>private</span><span twffan="done">:</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">virtual</span> <span twffan="done">void</span> f() { cout &lt;&lt; <span twffan="done">"Base::f"</span> &lt;&lt; endl; }</span></p>
<p>&nbsp;</p>
<p><span twffan="done">};</span></p>
<p><span twffan="done"><font size=3>&nbsp;</font></span></p>
<p><span twffan="done">class</span><span twffan="done"> Derive : <span twffan="done">public</span> Base{</span></p>
<p>&nbsp;</p>
<p><span twffan="done">};</span></p>
<p>&nbsp;</p>
<p><span twffan="done">typedef</span><span twffan="done"> <span twffan="done">void</span>(*Fun)(<span twffan="done">void</span>);</span></p>
<p>&nbsp;</p>
<p><span twffan="done">void</span><span twffan="done"> main() {</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp; </span>Derive d;</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp; </span>Fun&nbsp;pFun = (Fun)*((<span twffan="done">int</span>*)*(<span twffan="done">int</span>*)(&amp;d)+<span twffan="done">0</span>);</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp; </span>pFun();</span></p>
<p><span twffan="done">}</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1><span twffan="done"><font size=5>结束语</font></span></h1>
<p><font size=3><font face="Times New Roman">C++</font><span twffan="done">这门语言是一门</span><font face="Times New Roman">Magic</font><span twffan="done">的语言，对于程序员来说，我们似乎永远摸不清楚这门语言背着我们在干了什么。需要熟悉这门语言，我们就必需要了解</span><font face="Times New Roman">C++</font><span twffan="done">里面的那些东西，需要去了解</span><font face="Times New Roman">C++</font><span twffan="done">中那些危险的东西。不然，这是一种搬起石头砸自己脚的编程语言。</span></font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font size=3><span twffan="done">在文章束之前还是介绍一下自己吧。我从事软件研发有十个年头了，目前是软件开发技术主管，技术方面，主攻</span><font face="Times New Roman">Unix/C/C++</font><span twffan="done">，比较喜欢网络上的技术，比如分布式计算，网格计算，</span><font face="Times New Roman">P2P</font><span twffan="done">，</span><font face="Times New Roman">Ajax</font><span twffan="done">等一切和互联网相关的东西。管理方面比较擅长于团队建设，技术趋势分析，项目管理。欢迎大家和我交流，我的</span><font face="Times New Roman">MSN</font><span twffan="done">和</span><font face="Times New Roman">Email</font><span twffan="done">是：</span></font><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#104;&#97;&#111;&#101;&#108;&#64;&#104;&#111;&#116;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;"><font face="Times New Roman" color=#000080 size=3>haoel@hotmail.com</font></a><span twffan="done"><font face="Times New Roman" size=3>&nbsp; </font></span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<h1><font size=5><span twffan="done">附录一：</span>VC<span twffan="done">中查看虚函数表</span></font></h1>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font size=3><span twffan="done">我们可以在</span><font face="Times New Roman">VC</font><span twffan="done">的</span><font face="Times New Roman">IDE</font><span twffan="done">环境中的</span><font face="Times New Roman">Debug</font><span twffan="done">状态下展开类的实例就可以看到虚函数表了（并不是很完整的）</span></font></p>
<p><font size=3></font></p>
<p align=center><font size=3><span twffan="done"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_vtable_vc.JPG" twffan="done"></span></font></p>
<p align=center><font size=3></font></p>
<h1><font size=5><span twffan="done">附录</span><span twffan="done"> </span><span twffan="done">二：例程</span></font></h1>
<p><span twffan="done"><font size=3>下面是一个关于多重继承的虚函数表访问的例程：</font></span></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><span twffan="done">#include</span><span twffan="done"> <span twffan="done">&lt;iostream&gt;</span></span></p>
<p><span twffan="done">using</span><span twffan="done"> <span twffan="done">namespace</span> std;</span></p>
<p>&nbsp;</p>
<p><span twffan="done">class</span><span twffan="done"> Base1 {</span></p>
<p><span twffan="done">public</span><span twffan="done">:</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">virtual</span> <span twffan="done">void</span> f() { cout &lt;&lt; <span twffan="done">"Base1::f"</span> &lt;&lt; endl; }</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">virtual</span> <span twffan="done">void</span> g() { cout &lt;&lt; <span twffan="done">"Base1::g"</span> &lt;&lt; endl; }</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">virtual</span> <span twffan="done">void</span> h() { cout &lt;&lt; <span twffan="done">"Base1::h"</span> &lt;&lt; endl; }</span></p>
<p>&nbsp;</p>
<p><span twffan="done">};</span></p>
<p>&nbsp;</p>
<p><span twffan="done">class</span><span twffan="done"> Base2 {</span></p>
<p><span twffan="done">public</span><span twffan="done">:</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">virtual</span> <span twffan="done">void</span> f() { cout &lt;&lt; <span twffan="done">"Base2::f"</span> &lt;&lt; endl; }</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">virtual</span> <span twffan="done">void</span> g() { cout &lt;&lt; <span twffan="done">"Base2::g"</span> &lt;&lt; endl; }</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">virtual</span> <span twffan="done">void</span> h() { cout &lt;&lt; <span twffan="done">"Base2::h"</span> &lt;&lt; endl; }</span></p>
<p><span twffan="done">};</span></p>
<p>&nbsp;</p>
<p><span twffan="done">class</span><span twffan="done"> Base3 {</span></p>
<p><span twffan="done">public</span><span twffan="done">:</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">virtual</span> <span twffan="done">void</span> f() { cout &lt;&lt; <span twffan="done">"Base3::f"</span> &lt;&lt; endl; }</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">virtual</span> <span twffan="done">void</span> g() { cout &lt;&lt; <span twffan="done">"Base3::g"</span> &lt;&lt; endl; }</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">virtual</span> <span twffan="done">void</span> h() { cout &lt;&lt; <span twffan="done">"Base3::h"</span> &lt;&lt; endl; }</span></p>
<p><span twffan="done">};</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span twffan="done">class</span><span twffan="done"> Derive : <span twffan="done">public</span> Base1, <span twffan="done">public</span> Base2, <span twffan="done">public</span> Base3 {</span></p>
<p><span twffan="done">public</span><span twffan="done">:</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">virtual</span> <span twffan="done">void</span> f() { cout &lt;&lt; <span twffan="done">"Driver::f"</span> &lt;&lt; endl; }</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">virtual</span> <span twffan="done">void</span> g1() { cout &lt;&lt; <span twffan="done">"Driver::g1"</span> &lt;&lt; endl; }</span></p>
<p><span twffan="done">};</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span twffan="done">typedef</span><span twffan="done"> <span twffan="done">void</span>(*Fun)(<span twffan="done">void</span>);</span></p>
<p>&nbsp;</p>
<p><span twffan="done">int</span><span twffan="done"> main() </span></p>
<p><span twffan="done">{</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Fun pFun = NULL;</span></p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Derive d;</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">int</span>** pVtab = (<span twffan="done">int</span>**)&amp;d;</span></p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span twffan="done">//Base1's vtable</span></strong></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">//pFun = (Fun)*((int*)*(int*)((int*)&amp;d+0)+0);</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun = (Fun)pVtab[<span twffan="done">0</span>][<span twffan="done">0</span>];</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun();</span></p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">//pFun = (Fun)*((int*)*(int*)((int*)&amp;d+0)+1);</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun = (Fun)pVtab[<span twffan="done">0</span>][<span twffan="done">1</span>];</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun();</span></p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">//pFun = (Fun)*((int*)*(int*)((int*)&amp;d+0)+2);</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun = (Fun)pVtab[<span twffan="done">0</span>][<span twffan="done">2</span>];</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun();</span></p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">//Derive's vtable</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">//pFun = (Fun)*((int*)*(int*)((int*)&amp;d+0)+3);</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun = (Fun)pVtab[<span twffan="done">0</span>][<span twffan="done">3</span>];</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun();</span></p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">//The tail of the vtable</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun = (Fun)pVtab[<span twffan="done">0</span>][<span twffan="done">4</span>];</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>cout&lt;&lt;pFun&lt;&lt;endl;</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span twffan="done">//Base2's vtable</span></strong></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">//pFun = (Fun)*((int*)*(int*)((int*)&amp;d+1)+0);</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun = (Fun)pVtab[<span twffan="done">1</span>][<span twffan="done">0</span>];</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun();</span></p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">//pFun = (Fun)*((int*)*(int*)((int*)&amp;d+1)+1);</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun = (Fun)pVtab[<span twffan="done">1</span>][<span twffan="done">1</span>];</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun();</span></p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun = (Fun)pVtab[<span twffan="done">1</span>][<span twffan="done">2</span>];</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun(); </span></p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">//The tail of the vtable</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun = (Fun)pVtab[<span twffan="done">1</span>][<span twffan="done">3</span>];</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>cout&lt;&lt;pFun&lt;&lt;endl;</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span twffan="done">//Base3's vtable</span></strong></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">//pFun = (Fun)*((int*)*(int*)((int*)&amp;d+1)+0);</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun = (Fun)pVtab[<span twffan="done">2</span>][<span twffan="done">0</span>];</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun();</span></p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">//pFun = (Fun)*((int*)*(int*)((int*)&amp;d+1)+1);</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun = (Fun)pVtab[<span twffan="done">2</span>][<span twffan="done">1</span>];</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun();</span></p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun = (Fun)pVtab[<span twffan="done">2</span>][<span twffan="done">2</span>];</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun(); </span></p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">//The tail of the vtable</span></span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pFun = (Fun)pVtab[<span twffan="done">2</span>][<span twffan="done">3</span>];</span></p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>cout&lt;&lt;pFun&lt;&lt;endl;</span></p>
<p>&nbsp;</p>
<p><span twffan="done"><span twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span twffan="done">return</span> <span twffan="done">0</span>;</span></p>
<p><span twffan="done">}</span></p>
<p>&nbsp;</p>
<p><font size=3><strong><font face="Times New Roman">(</font></strong><strong><span twffan="done">转载时请注明作者和出处。未经许可，请勿用于商业用途</span><font face="Times New Roman">)</font></strong></font></p>
<p><font face="Times New Roman" size=3>&nbsp;</font></p>
<p><font size=3><span twffan="done">更多文章请访问我的</span><font face="Times New Roman">Blog: </font></font><a href="http://blog.csdn.net/haoel"><font face="Times New Roman" color=#000080 size=3>http://blog.csdn.net/haoel</font></a><font face="Times New Roman" size=3> </font></p><img src ="http://www.cppblog.com/mzty/aggbug/42877.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2008-02-18 13:29 <a href="http://www.cppblog.com/mzty/archive/2008/02/18/42877.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>本博客所有精华随笔索引</title><link>http://www.cppblog.com/mzty/archive/2008/01/17/41318.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Thu, 17 Jan 2008 02:14:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2008/01/17/41318.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/41318.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2008/01/17/41318.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/41318.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/41318.html</trackback:ping><description><![CDATA[<p><br>总结：<a href="http://www.cppblog.com/mzty/archive/2007/08/13/29922.html"><br><br>http://www.cppblog.com/mzty/archive/2007/08/13/29922.html</a>&nbsp; C++高级</p>
<p><a href="http://www.cppblog.com/mzty/archive/2007/03/02/19109.html">http://www.cppblog.com/mzty/archive/2007/03/02/19109.html</a>&nbsp; C++基础</p>
<p><a href="http://www.cppblog.com/mzty/archive/2007/04/16/22064.html">http://www.cppblog.com/mzty/archive/2007/04/16/22064.html</a>&nbsp; C#界面，C++核心算法</p>
<p><a href="http://www.cppblog.com/mzty/archive/2007/03/04/19163.html">http://www.cppblog.com/mzty/archive/2007/03/04/19163.html</a>&nbsp; 设计模式</p>
<p><a href="http://www.cppblog.com/mzty/archive/2007/03/29/20893.html">http://www.cppblog.com/mzty/archive/2007/03/29/20893.html</a>&nbsp; 64bit，FW3.0随笔分类 </p>
<p><a href="http://www.cppblog.com/mzty/archive/2007/03/29/20892.html">http://www.cppblog.com/mzty/archive/2007/03/29/20892.html</a>&nbsp; windows脚本技术</p>
<p><a href="http://www.cppblog.com/mzty/archive/2007/03/04/19167.html">http://www.cppblog.com/mzty/archive/2007/03/04/19167.html</a>&nbsp; C#基础</p><img src ="http://www.cppblog.com/mzty/aggbug/41318.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2008-01-17 10:14 <a href="http://www.cppblog.com/mzty/archive/2008/01/17/41318.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#的Form通过CLI调用C++的DLL</title><link>http://www.cppblog.com/mzty/archive/2007/12/25/39610.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Tue, 25 Dec 2007 11:14:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/12/25/39610.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/39610.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/12/25/39610.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/39610.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/39610.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一 方法&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C#的project调用C++的DLL，一般也有3中方法：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1）最简单的方法，通过PInvoke，但是只能调用全局function，不能调用Class。&nbsp;&nbsp;&...&nbsp;&nbsp;<a href='http://www.cppblog.com/mzty/archive/2007/12/25/39610.html'>阅读全文</a><img src ="http://www.cppblog.com/mzty/aggbug/39610.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-12-25 19:14 <a href="http://www.cppblog.com/mzty/archive/2007/12/25/39610.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>NativeC++通过CLI调用C#的Form</title><link>http://www.cppblog.com/mzty/archive/2007/12/25/39555.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Tue, 25 Dec 2007 02:51:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/12/25/39555.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/39555.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/12/25/39555.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/39555.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/39555.html</trackback:ping><description><![CDATA[<br>一 调用方法<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Native C++的project调用C#的DLL，一般有3中方法：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1）通过COM封装<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2）通过CLI/C++的Wrapper<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3)&nbsp; 在VS中可以直接修改NativeC++的project或是部分文件为使用CLR来调用C#的DLL<br><br>二 实例<br>1）C#的一个MyForm类，有public函数ShowMyForm（）<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: #0000ff">using</span><span style="COLOR: #000000">&nbsp;System;<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;System.Collections.Generic;<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;System.Text;<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;System.Windows.Forms;<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">namespace</span><span style="COLOR: #000000">&nbsp;CsharpDLL<br><img id=Codehighlighter1_116_1454_Open_Image onclick="this.style.display='none'; Codehighlighter1_116_1454_Open_Text.style.display='none'; Codehighlighter1_116_1454_Closed_Image.style.display='inline'; Codehighlighter1_116_1454_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_116_1454_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_116_1454_Closed_Text.style.display='none'; Codehighlighter1_116_1454_Open_Image.style.display='inline'; Codehighlighter1_116_1454_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_116_1454_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_116_1454_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">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MyForm&nbsp;:&nbsp;Form<br><img id=Codehighlighter1_153_1452_Open_Image onclick="this.style.display='none'; Codehighlighter1_153_1452_Open_Text.style.display='none'; Codehighlighter1_153_1452_Closed_Image.style.display='inline'; Codehighlighter1_153_1452_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_153_1452_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_153_1452_Closed_Text.style.display='none'; Codehighlighter1_153_1452_Open_Image.style.display='inline'; Codehighlighter1_153_1452_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_153_1452_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_153_1452_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">private</span><span style="COLOR: #000000">&nbsp;Button&nbsp;button1;<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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;ShowMyForm()<br><img id=Codehighlighter1_229_270_Open_Image onclick="this.style.display='none'; Codehighlighter1_229_270_Open_Text.style.display='none'; Codehighlighter1_229_270_Closed_Image.style.display='inline'; Codehighlighter1_229_270_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_229_270_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_229_270_Closed_Text.style.display='none'; Codehighlighter1_229_270_Open_Image.style.display='inline'; Codehighlighter1_229_270_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_229_270_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_229_270_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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.ShowDialog();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;MyForm()<br><img id=Codehighlighter1_304_448_Open_Image onclick="this.style.display='none'; Codehighlighter1_304_448_Open_Text.style.display='none'; Codehighlighter1_304_448_Closed_Image.style.display='inline'; Codehighlighter1_304_448_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_304_448_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_304_448_Closed_Text.style.display='none'; Codehighlighter1_304_448_Open_Image.style.display='inline'; Codehighlighter1_304_448_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_304_448_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_304_448_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;&nbsp;&nbsp;&nbsp;&nbsp;InitializeComponent();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.Text&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">MyForm</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.StartPosition&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;FormStartPosition.CenterScreen;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;InitializeComponent()<br><img id=Codehighlighter1_501_1303_Open_Image onclick="this.style.display='none'; Codehighlighter1_501_1303_Open_Text.style.display='none'; Codehighlighter1_501_1303_Closed_Image.style.display='inline'; Codehighlighter1_501_1303_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_501_1303_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_501_1303_Closed_Text.style.display='none'; Codehighlighter1_501_1303_Open_Image.style.display='inline'; Codehighlighter1_501_1303_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_501_1303_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_501_1303_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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.button1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;System.Windows.Forms.Button();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.SuspendLayout();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;button1<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.button1.Location&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;System.Drawing.Point(</span><span style="COLOR: #000000">110</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">74</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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.button1.Name&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">button1</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.button1.Size&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;System.Drawing.Size(</span><span style="COLOR: #000000">75</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">23</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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.button1.TabIndex&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.button1.Text&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">TestMessageBox</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.button1.UseVisualStyleBackColor&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.button1.Click&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;System.EventHandler(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.button1_Click);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;MyForm<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.ClientSize&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;System.Drawing.Size(</span><span style="COLOR: #000000">292</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">266</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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.Controls.Add(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.button1);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.Name&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">MyForm</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.ResumeLayout(</span><span style="COLOR: #0000ff">false</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/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;button1_Click(</span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">&nbsp;sender,&nbsp;EventArgs&nbsp;e)<br><img id=Codehighlighter1_1377_1446_Open_Image onclick="this.style.display='none'; Codehighlighter1_1377_1446_Open_Text.style.display='none'; Codehighlighter1_1377_1446_Closed_Image.style.display='inline'; Codehighlighter1_1377_1446_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1377_1446_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1377_1446_Closed_Text.style.display='none'; Codehighlighter1_1377_1446_Open_Image.style.display='inline'; Codehighlighter1_1377_1446_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1377_1446_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_1377_1446_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;&nbsp;&nbsp;&nbsp;&nbsp;MessageBox.Show(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hello,&nbsp;i&nbsp;am&nbsp;a&nbsp;Csharp&nbsp;Form!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></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/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>
<br>2）C#的exe调用<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: #0000ff">using</span><span style="COLOR: #000000">&nbsp;System;<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;System.Collections.Generic;<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;System.Text;<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">namespace</span><span style="COLOR: #000000">&nbsp;CsharpTest<br><img id=Codehighlighter1_89_411_Open_Image onclick="this.style.display='none'; Codehighlighter1_89_411_Open_Text.style.display='none'; Codehighlighter1_89_411_Closed_Image.style.display='inline'; Codehighlighter1_89_411_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_89_411_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_89_411_Closed_Text.style.display='none'; Codehighlighter1_89_411_Open_Image.style.display='inline'; Codehighlighter1_89_411_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_89_411_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_89_411_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">class</span><span style="COLOR: #000000">&nbsp;Program<br><img id=Codehighlighter1_113_409_Open_Image onclick="this.style.display='none'; Codehighlighter1_113_409_Open_Text.style.display='none'; Codehighlighter1_113_409_Closed_Image.style.display='inline'; Codehighlighter1_113_409_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_113_409_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_113_409_Closed_Text.style.display='none'; Codehighlighter1_113_409_Open_Image.style.display='inline'; Codehighlighter1_113_409_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_113_409_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_113_409_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">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Main(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">[]&nbsp;args)<br><img id=Codehighlighter1_163_403_Open_Image onclick="this.style.display='none'; Codehighlighter1_163_403_Open_Text.style.display='none'; Codehighlighter1_163_403_Closed_Image.style.display='inline'; Codehighlighter1_163_403_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_163_403_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_163_403_Closed_Text.style.display='none'; Codehighlighter1_163_403_Open_Image.style.display='inline'; Codehighlighter1_163_403_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_163_403_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_163_403_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;&nbsp;&nbsp;&nbsp;&nbsp;System.Console.WriteLine(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Csharp&nbsp;main&nbsp;funtion&nbsp;start:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CsharpDLL.MyForm&nbsp;myForm&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;CsharpDLL.MyForm();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myForm.ShowMyForm();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Console.WriteLine(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Csharp&nbsp;main&nbsp;function&nbsp;end!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></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/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>
<br>3）CLI/C++的warpper，DLLexport函数CallCsharpForm（），此函数中调用C#的MyForm<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: #000000">CPPCLIPROXYDLLFORCSHARPDLL_API&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;CallCsharpForm();<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">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">../debug/CsharpDll.dll</span><span style="COLOR: #000000">"</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>CPPCLIPROXYDLLFORCSHARPDLL_API&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;CallCsharpForm()<br><img id=Codehighlighter1_141_222_Open_Image onclick="this.style.display='none'; Codehighlighter1_141_222_Open_Text.style.display='none'; Codehighlighter1_141_222_Closed_Image.style.display='inline'; Codehighlighter1_141_222_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_141_222_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_141_222_Closed_Text.style.display='none'; Codehighlighter1_141_222_Open_Image.style.display='inline'; Codehighlighter1_141_222_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_141_222_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_141_222_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CsharpDLL::MyForm</span><span style="COLOR: #000000">^</span><span style="COLOR: #000000">&nbsp;myForm&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;gcnew&nbsp;CsharpDLL::MyForm();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;myForm</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">ShowMyForm();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>4）NativeC++的exe调用CLI的Wrapper来间接的调用MyForm<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: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</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">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>#pragma&nbsp;comment(lib,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">../debug/CppCLIProxyDLLForCsharpDLL.lib</span><span style="COLOR: #000000">"</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;CallCsharpForm();<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;_tmain(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;_TCHAR</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br><img id=Codehighlighter1_166_300_Open_Image onclick="this.style.display='none'; Codehighlighter1_166_300_Open_Text.style.display='none'; Codehighlighter1_166_300_Closed_Image.style.display='inline'; Codehighlighter1_166_300_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_166_300_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_166_300_Closed_Text.style.display='none'; Codehighlighter1_166_300_Open_Image.style.display='inline'; Codehighlighter1_166_300_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_166_300_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_166_300_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;std::cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;Cpp&nbsp;Main&nbsp;function&nbsp;start:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">std::endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CallCsharpForm();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;std::cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;Cpp&nbsp;Main&nbsp;function&nbsp;end!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">std::endl;<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">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>三 总结<br>要调试最好修改编译选项为Mixed。<br><br>代码下载： <a href="http://www.cppblog.com/Files/mzty/CppCallCsharpByCLI.rar">http://www.cppblog.com/Files/mzty/CppCallCsharpByCLI.rar</a><br><img src ="http://www.cppblog.com/mzty/aggbug/39555.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-12-25 10:51 <a href="http://www.cppblog.com/mzty/archive/2007/12/25/39555.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CLI/C++中混合类的使用</title><link>http://www.cppblog.com/mzty/archive/2007/12/24/39517.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Mon, 24 Dec 2007 09:47:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/12/24/39517.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/39517.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/12/24/39517.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/39517.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/39517.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一 混合类所谓混合类是指CLI/C++中native的Class中可以包含CLR对象，CLR的class也可以包含Naitve的对象。1）native的class中包含CLR对象，必须通过gcroot&lt;&gt;或auto_gcroot&lt;&gt;。2）CLR中的class中包含native的对象，必须是指针，也可以使用高手写的CAutoNativePtr智能指针。注意：C#中不能...&nbsp;&nbsp;<a href='http://www.cppblog.com/mzty/archive/2007/12/24/39517.html'>阅读全文</a><img src ="http://www.cppblog.com/mzty/aggbug/39517.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-12-24 17:47 <a href="http://www.cppblog.com/mzty/archive/2007/12/24/39517.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个CLI/C++的DLL同时被C#的exe和NativeC++的exe调用</title><link>http://www.cppblog.com/mzty/archive/2007/12/20/39165.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Thu, 20 Dec 2007 14:47:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/12/20/39165.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/39165.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/12/20/39165.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/39165.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/39165.html</trackback:ping><description><![CDATA[<br>&nbsp;一&nbsp;引子<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1）使用VS2005，Native C++，C#，CLI/C++。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2）主要介绍CLI/C++和Native C++, C#的交互，最总能够实现以CLI/C++为中介的Native C++与C#的互调。<br><br>&nbsp;二 实例<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1）实现一个CLI/C++的Dll，在此Dll中包含一个RefClass能够被C#的exe调用。（实现过程：在VS中建立C++ CLR Class library 的一个Project，然后增加一个类RefClass）代码如下：<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;refclass.h文件：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#pragma&nbsp;once&nbsp;<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">namespace</span><span style="COLOR: #000000">&nbsp;ClrCppDll&nbsp;<br><img id=Codehighlighter1_36_196_Open_Image onclick="this.style.display='none'; Codehighlighter1_36_196_Open_Text.style.display='none'; Codehighlighter1_36_196_Closed_Image.style.display='inline'; Codehighlighter1_36_196_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_36_196_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_36_196_Closed_Text.style.display='none'; Codehighlighter1_36_196_Open_Image.style.display='inline'; Codehighlighter1_36_196_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_36_196_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_36_196_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">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">ref</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;RefClass<br><img id=Codehighlighter1_66_193_Open_Image onclick="this.style.display='none'; Codehighlighter1_66_193_Open_Text.style.display='none'; Codehighlighter1_66_193_Closed_Image.style.display='inline'; Codehighlighter1_66_193_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_66_193_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_66_193_Closed_Text.style.display='none'; Codehighlighter1_66_193_Open_Image.style.display='inline'; Codehighlighter1_66_193_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_66_193_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_66_193_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">public</span><span style="COLOR: #000000">:<br><img id=Codehighlighter1_89_90_Open_Image onclick="this.style.display='none'; Codehighlighter1_89_90_Open_Text.style.display='none'; Codehighlighter1_89_90_Closed_Image.style.display='inline'; Codehighlighter1_89_90_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_89_90_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_89_90_Closed_Text.style.display='none'; Codehighlighter1_89_90_Open_Image.style.display='inline'; Codehighlighter1_89_90_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RefClass()</span><span id=Codehighlighter1_89_90_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_89_90_Open_Text><span style="COLOR: #000000">{}</span></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;RefClass(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_x,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_y)&nbsp;:&nbsp;x(_x),&nbsp;y(_y)<br><img id=Codehighlighter1_136_140_Open_Image onclick="this.style.display='none'; Codehighlighter1_136_140_Open_Text.style.display='none'; Codehighlighter1_136_140_Closed_Image.style.display='inline'; Codehighlighter1_136_140_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_136_140_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_136_140_Closed_Text.style.display='none'; Codehighlighter1_136_140_Open_Image.style.display='inline'; Codehighlighter1_136_140_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_136_140_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_136_140_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;PrintSelf();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</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;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;x;<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">int</span><span style="COLOR: #000000">&nbsp;y;<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></div>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;refclass.cpp文件：<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: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</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">"</span><span style="COLOR: #000000">refclass.h</span><span style="COLOR: #000000">"</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">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;System;<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;ClrCppDll;<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;RefClass::PrintSelf()<br><img id=Codehighlighter1_122_270_Open_Image onclick="this.style.display='none'; Codehighlighter1_122_270_Open_Text.style.display='none'; Codehighlighter1_122_270_Closed_Image.style.display='inline'; Codehighlighter1_122_270_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_122_270_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_122_270_Closed_Text.style.display='none'; Codehighlighter1_122_270_Open_Image.style.display='inline'; Codehighlighter1_122_270_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_122_270_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_122_270_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;System::Console::WriteLine(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">hello,&nbsp;i&nbsp;am&nbsp;a&nbsp;ref&nbsp;cpp&nbsp;class</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;System::Console::WriteLine(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">x&nbsp;is&nbsp;{0}</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,x);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;System::Console::WriteLine(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">y&nbsp;is&nbsp;{0}</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,y);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2）能够调用上面第1）步中的CLI/C++的Dll中class的C#的exe。（实现过程：在VS建立C#的console Application，然后reference 前面的1)生成的Dll）代码如下：<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Program.cs文件：<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: #0000ff">using</span><span style="COLOR: #000000">&nbsp;System;<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;System.Collections.Generic;<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;System.Text;<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">namespace</span><span style="COLOR: #000000">&nbsp;CsharpTest<br><img id=Codehighlighter1_89_286_Open_Image onclick="this.style.display='none'; Codehighlighter1_89_286_Open_Text.style.display='none'; Codehighlighter1_89_286_Closed_Image.style.display='inline'; Codehighlighter1_89_286_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_89_286_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_89_286_Closed_Text.style.display='none'; Codehighlighter1_89_286_Open_Image.style.display='inline'; Codehighlighter1_89_286_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_89_286_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_89_286_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">class</span><span style="COLOR: #000000">&nbsp;Program<br><img id=Codehighlighter1_113_284_Open_Image onclick="this.style.display='none'; Codehighlighter1_113_284_Open_Text.style.display='none'; Codehighlighter1_113_284_Closed_Image.style.display='inline'; Codehighlighter1_113_284_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_113_284_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_113_284_Closed_Text.style.display='none'; Codehighlighter1_113_284_Open_Image.style.display='inline'; Codehighlighter1_113_284_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_113_284_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_113_284_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">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Main(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">[]&nbsp;args)<br><img id=Codehighlighter1_163_278_Open_Image onclick="this.style.display='none'; Codehighlighter1_163_278_Open_Text.style.display='none'; Codehighlighter1_163_278_Closed_Image.style.display='inline'; Codehighlighter1_163_278_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_163_278_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_163_278_Closed_Text.style.display='none'; Codehighlighter1_163_278_Open_Image.style.display='inline'; Codehighlighter1_163_278_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_163_278_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_163_278_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;&nbsp;&nbsp;&nbsp;&nbsp;ClrCppDll.RefClass&nbsp;refClass&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ClrCppDll.RefClass(</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">4</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;&nbsp;&nbsp;&nbsp;&nbsp;refClass.PrintSelf();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></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/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br><span style="BACKGROUND-COLOR: #ff0000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;上面2步的代码下载</span>：<a href="http://www.cppblog.com/Files/mzty/CSharpCPPCLI1.rar">http://www.cppblog.com/Files/mzty/CSharpCPPCLI1.rar</a>&nbsp;（实现CLI/C++的dll能够被C#调用）<br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp; 3）对1）实现的CLI/C++的Dll中增加能够被Native C++调用的NativeClass。代码如下：<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NativeClass.h文件：<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: #000000">#pragma&nbsp;once<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">namespace</span><span style="COLOR: #000000">&nbsp;ClrCppDll<br><img id=Codehighlighter1_34_207_Open_Image onclick="this.style.display='none'; Codehighlighter1_34_207_Open_Text.style.display='none'; Codehighlighter1_34_207_Closed_Image.style.display='inline'; Codehighlighter1_34_207_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_34_207_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_34_207_Closed_Text.style.display='none'; Codehighlighter1_34_207_Open_Image.style.display='inline'; Codehighlighter1_34_207_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_34_207_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_34_207_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">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;NativeClass<br><img id=Codehighlighter1_63_204_Open_Image onclick="this.style.display='none'; Codehighlighter1_63_204_Open_Text.style.display='none'; Codehighlighter1_63_204_Closed_Image.style.display='inline'; Codehighlighter1_63_204_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_63_204_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_63_204_Closed_Text.style.display='none'; Codehighlighter1_63_204_Open_Image.style.display='inline'; Codehighlighter1_63_204_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_63_204_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_63_204_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<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">public</span><span style="COLOR: #000000">:<br><img id=Codehighlighter1_93_94_Open_Image onclick="this.style.display='none'; Codehighlighter1_93_94_Open_Text.style.display='none'; Codehighlighter1_93_94_Closed_Image.style.display='inline'; Codehighlighter1_93_94_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_93_94_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_93_94_Closed_Text.style.display='none'; Codehighlighter1_93_94_Open_Image.style.display='inline'; Codehighlighter1_93_94_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NativeClass()</span><span id=Codehighlighter1_93_94_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_93_94_Open_Text><span style="COLOR: #000000">{}</span></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;&nbsp;&nbsp;&nbsp;&nbsp;NativeClass(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_x,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;_y)&nbsp;:&nbsp;x(_x),&nbsp;y(_y)<br><img id=Codehighlighter1_145_146_Open_Image onclick="this.style.display='none'; Codehighlighter1_145_146_Open_Text.style.display='none'; Codehighlighter1_145_146_Closed_Image.style.display='inline'; Codehighlighter1_145_146_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_145_146_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_145_146_Closed_Text.style.display='none'; Codehighlighter1_145_146_Open_Image.style.display='inline'; Codehighlighter1_145_146_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_145_146_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_145_146_Open_Text><span style="COLOR: #000000">{}</span></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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;printSelf();<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;&nbsp;&nbsp;&nbsp;&nbsp;</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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;x;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;y;&nbsp;&nbsp;&nbsp;&nbsp;<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></div>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NativeClass.cpp文件：<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: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</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">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>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">nativeclass.h</span><span style="COLOR: #000000">"</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">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;ClrCppDll;<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;NativeClass::printSelf()<br><img id=Codehighlighter1_124_257_Open_Image onclick="this.style.display='none'; Codehighlighter1_124_257_Open_Text.style.display='none'; Codehighlighter1_124_257_Closed_Image.style.display='inline'; Codehighlighter1_124_257_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_124_257_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_124_257_Closed_Text.style.display='none'; Codehighlighter1_124_257_Open_Image.style.display='inline'; Codehighlighter1_124_257_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_124_257_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_124_257_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;std::cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">hello,i&nbsp;am&nbsp;a&nbsp;native&nbsp;cpp&nbsp;class!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">std::endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;std::cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">x&nbsp;is&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">x</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">std::endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;std::cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">y&nbsp;is&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">y</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">std::endl;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="BACKGROUND-COLOR: #ff0000">问题：</span> <span style="COLOR: red">如果我们直接在NativeC++的exe调用上面CLI/C++中的NativeClass，会有问题，Error&nbsp;1&nbsp;error C3381: 'CppClrDll::NativeClass' : assembly access specifiers are only available in code compiled with a /clr option&nbsp;d:\cppandcsharpinteractivetest\csharpcppcli\clrcppdll\nativeclass.h&nbsp;8，这是为什么那，我们想想我们一般的Native C++的DLL的调用，都要将要被调用的Class或funtion导出才可以调用，想到这里我们也对我们的NativeClass进行导出。（怎么导出可以看下面的代码）但是当增加了对NativeClass的导出，调用的时候仍然有上面的error，Error&nbsp;1&nbsp;error C3381: 'CppClrDll::NativeClass' : assembly access specifiers are only available in code compiled with a /clr option&nbsp;d:\cppandcsharpinteractivetest\csharpcppcli\clrcppdll\nativeclass.h&nbsp;9，最后只有查找资料（没有找到）问别人（没有问到），最后想到使用导出函数试试，一试果然可行啊，哈哈哈，so Happy</span>！<span style="COLOR: #00ccff">其实后来发现是我加的导出__declspec(dllexport)的位置不对，应该是在class关键字后面，总之导出类也是可以的。</span>导出类的代码可以下载新的sample，增加导出和导出的函数代码如下：<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (导出不久需要下面的2文件，还的定义宏 CLR_CPP_DLL在编译选项中，或直接写在文件中)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clrcppdll.h<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;ClrCppDll.h</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>#pragma&nbsp;once<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>#ifdef&nbsp;CLR_CPP_DLL<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;DLLIMPEXP&nbsp;__declspec(dllexport)</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#else</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;DLLIMPEXP</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#endif</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">namespace</span><span style="COLOR: #000000">&nbsp;ClrCppDll&nbsp;<br><img id=Codehighlighter1_142_190_Open_Image onclick="this.style.display='none'; Codehighlighter1_142_190_Open_Text.style.display='none'; Codehighlighter1_142_190_Closed_Image.style.display='inline'; Codehighlighter1_142_190_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_142_190_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_142_190_Closed_Text.style.display='none'; Codehighlighter1_142_190_Open_Image.style.display='inline'; Codehighlighter1_142_190_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_142_190_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_142_190_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;DLLIMPEXP&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;&nbsp;CallNativeClassPrintSelf();&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clrcppdll.cpp文件：<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;This&nbsp;is&nbsp;the&nbsp;main&nbsp;DLL&nbsp;file.</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">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</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">"</span><span style="COLOR: #000000">NativeClass.h</span><span style="COLOR: #000000">"</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">"</span><span style="COLOR: #000000">ClrCppDll.h</span><span style="COLOR: #000000">"</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>DLLIMPEXP&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;&nbsp;ClrCppDll::CallNativeClassPrintSelf()<br><img id=Codehighlighter1_154_212_Open_Image onclick="this.style.display='none'; Codehighlighter1_154_212_Open_Text.style.display='none'; Codehighlighter1_154_212_Closed_Image.style.display='inline'; Codehighlighter1_154_212_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_154_212_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_154_212_Closed_Text.style.display='none'; Codehighlighter1_154_212_Open_Image.style.display='inline'; Codehighlighter1_154_212_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_154_212_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_154_212_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ClrCppDll::NativeClass&nbsp;test(</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">20</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;test.printSelf();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4）建立一个NativeC++的exe来调用1）生成的CLI/C++的Dll中的3）增加的NativeClass（实现过程：建立一个Native C++的console application）代码如下：<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cpptest.cpp文件：（经过上一步问题的反复折磨，终于搞定）（同时别忘了要在编译选项中指定lib和lib的路径）<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;CppTest.cpp&nbsp;:&nbsp;Defines&nbsp;the&nbsp;entry&nbsp;point&nbsp;for&nbsp;the&nbsp;console&nbsp;application.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></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">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</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">"</span><span style="COLOR: #000000">../ClrCppDll/clrcppdll.h</span><span style="COLOR: #000000">"</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;_tmain(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;_TCHAR</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br><img id=Codehighlighter1_168_280_Open_Image onclick="this.style.display='none'; Codehighlighter1_168_280_Open_Text.style.display='none'; Codehighlighter1_168_280_Closed_Image.style.display='inline'; Codehighlighter1_168_280_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_168_280_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_168_280_Closed_Text.style.display='none'; Codehighlighter1_168_280_Open_Image.style.display='inline'; Codehighlighter1_168_280_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_168_280_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_168_280_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_171_226_Open_Image onclick="this.style.display='none'; Codehighlighter1_171_226_Open_Text.style.display='none'; Codehighlighter1_171_226_Closed_Image.style.display='inline'; Codehighlighter1_171_226_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_171_226_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_171_226_Closed_Text.style.display='none'; Codehighlighter1_171_226_Open_Image.style.display='inline'; Codehighlighter1_171_226_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_171_226_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">/**/</span><span id=Codehighlighter1_171_226_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">ClrCppDll::NativeClass&nbsp;test(5,6);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;test.PrintSelf();</span><span style="COLOR: #008000">*/</span></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;ClrCppDll::CallNativeClassPrintSelf();<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">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br><br>&nbsp;&nbsp;&nbsp;上面四步总代码下载：<a href="http://www.cppblog.com/Files/mzty/CSharpCPPCLI2.rar">http://www.cppblog.com/Files/mzty/CSharpCPPCLI2.rar</a>&nbsp;（实现CLI/C++的dll同时被Native C++和C#的调用）<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5）扩展，增加在NativeClass中调用RefClass的funtion, 和RefClass中调用NativeClass的function。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;代码下载：<a href="http://www.cppblog.com/Files/mzty/CSharpCPPCLI3.rar">http://www.cppblog.com/Files/mzty/CSharpCPPCLI3.rar</a>&nbsp;（最后代码下载，包含NativeClass与RefClass的互调）<br>&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;<a href="http://www.cppblog.com/Files/mzty/CSharpCPPCLI32.zip">http://www.cppblog.com/Files/mzty/CSharpCPPCLI32.zip</a>&nbsp;（包含native class的导出也调用）<br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;三 总结<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1) CLI/C++中如果想导出让NativeC++使用，则最好导出函数,也可以导出类。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2) CLI/C++的DLL可以没有像一般的NativeC++的Dll中的DllMain（）函数。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3) CLI/C++如果想导出让C#使用，则一般是ref class。<br><br><br><br><br><br><br><br><img src ="http://www.cppblog.com/mzty/aggbug/39165.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-12-20 22:47 <a href="http://www.cppblog.com/mzty/archive/2007/12/20/39165.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>堆栈，堆栈，堆和栈的区别（再转）</title><link>http://www.cppblog.com/mzty/archive/2007/12/03/37679.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Mon, 03 Dec 2007 05:36:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/12/03/37679.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/37679.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/12/03/37679.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/37679.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/37679.html</trackback:ping><description><![CDATA[<div class=postbody>来自任我行C++blog：<br><br><br>
<div class=postbody>堆和栈的区别<br>一、预备知识—程序的内存分配<br>一个由c/C++编译的程序占用的内存分为以下几个部分<br>1、栈区（stack）—&nbsp;由编译器自动分配释放&nbsp;，存放函数的参数值，局部变量的值等。其操作方式类似于数据结构中的栈。<br>2、堆区（heap）&nbsp;—&nbsp;一般由程序员分配释放，&nbsp;若程序员不释放，程序结束时可能由OS回收&nbsp;。注意它与数据结构中的堆是两回事，分配方式倒是类似于链表，呵呵。<br>3、全局区（静态区）（static）—，全局变量和静态变量的存储是放在一块的，初始化的全局变量和静态变量在一块区域，&nbsp;未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。&nbsp;-&nbsp;程序结束后有系统释放&nbsp;<br>4、文字常量区—常量字符串就是放在这里的。&nbsp;程序结束后由系统释放<br>5、程序代码区—存放函数体的二进制代码。<br>二、例子程序&nbsp;<br>这是一个前辈写的，非常详细&nbsp;<br>//main.cpp&nbsp;<br>int&nbsp;a&nbsp;=&nbsp;0;&nbsp;全局初始化区&nbsp;<br>char&nbsp;*p1;&nbsp;全局未初始化区&nbsp;<br>main()&nbsp;<br>{&nbsp;<br>int&nbsp;b;&nbsp;栈&nbsp;<br>char&nbsp;s[]&nbsp;=&nbsp;"abc";&nbsp;栈&nbsp;<br>char&nbsp;*p2;&nbsp;栈&nbsp;<br>char&nbsp;*p3&nbsp;=&nbsp;"123456";&nbsp;123456\0在常量区，p3在栈上。&nbsp;<br>static&nbsp;int&nbsp;c&nbsp;=0；&nbsp;全局（静态）初始化区&nbsp;<br>p1&nbsp;=&nbsp;(char&nbsp;*)malloc(10);&nbsp;<br>p2&nbsp;=&nbsp;(char&nbsp;*)malloc(20);&nbsp;<br>分配得来得10和20字节的区域就在堆区。&nbsp;<br>strcpy(p1,&nbsp;"123456");&nbsp;123456\0放在常量区，编译器可能会将它与p3所指向的"123456"优化成一个地方。&nbsp;<br>}&nbsp;
<p>&#160;</p>
<p><br>二、堆和栈的理论知识&nbsp;<br>2.1申请方式&nbsp;<br>stack:&nbsp;<br>由系统自动分配。&nbsp;例如，声明在函数中一个局部变量&nbsp;int&nbsp;b;&nbsp;系统自动在栈中为b开辟空间&nbsp;<br>heap:&nbsp;<br>需要程序员自己申请，并指明大小，在c中malloc函数&nbsp;<br>如p1&nbsp;=&nbsp;(char&nbsp;*)malloc(10);&nbsp;<br>在C++中用new运算符&nbsp;<br>如p2&nbsp;=&nbsp;(char&nbsp;*)malloc(10);&nbsp;<br>但是注意p1、p2本身是在栈中的。&nbsp;</p>
<p><br>2.2&nbsp;<br>申请后系统的响应&nbsp;<br>栈：只要栈的剩余空间大于所申请空间，系统将为程序提供内存，否则将报异常提示栈溢出。&nbsp;<br>堆：首先应该知道操作系统有一个记录空闲内存地址的链表，当系统收到程序的申请时，&nbsp;<br>会遍历该链表，寻找第一个空间大于所申请空间的堆结点，然后将该结点从空闲结点链表中删除，并将该结点的空间分配给程序，另外，对于大多数系统，会在这块内存空间中的首地址处记录本次分配的大小，这样，代码中的delete语句才能正确的释放本内存空间。另外，由于找到的堆结点的大小不一定正好等于申请的大小，系统会自动的将多余的那部分重新放入空闲链表中。&nbsp;</p>
<p>2.3申请大小的限制&nbsp;<br>栈：在Windows下,栈是向低地址扩展的数据结构，是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的，在WINDOWS下，栈的大小是2M（也有的说是1M，总之是一个编译时就确定的常数），如果申请的空间超过栈的剩余空间时，将提示overflow。因此，能从栈获得的空间较小。&nbsp;<br>堆：堆是向高地址扩展的数据结构，是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的，自然是不连续的，而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见，堆获得的空间比较灵活，也比较大。&nbsp;</p>
<p><br>2.4申请效率的比较：&nbsp;<br>栈由系统自动分配，速度较快。但程序员是无法控制的。&nbsp;<br>堆是由new分配的内存，一般速度比较慢，而且容易产生内存碎片,不过用起来最方便.&nbsp;<br>另外，在WINDOWS下，最好的方式是用VirtualAlloc分配内存，他不是在堆，也不是在栈是直接在进程的地址空间中保留一快内存，虽然用起来最不方便。但是速度快，也最灵活。&nbsp;</p>
<p>2.5堆和栈中的存储内容&nbsp;<br>栈：&nbsp;在函数调用时，第一个进栈的是主函数中后的下一条指令（函数调用语句的下一条可执行语句）的地址，然后是函数的各个参数，在大多数的C编译器中，参数是由右往左入栈的，然后是函数中的局部变量。注意静态变量是不入栈的。&nbsp;<br>当本次函数调用结束后，局部变量先出栈，然后是参数，最后栈顶指针指向最开始存的地址，也就是主函数中的下一条指令，程序由该点继续运行。&nbsp;<br>堆：一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。&nbsp;</p>
<p>2.6存取效率的比较&nbsp;</p>
<p>char&nbsp;s1[]&nbsp;=&nbsp;"aaaaaaaaaaaaaaa";&nbsp;<br>char&nbsp;*s2&nbsp;=&nbsp;"bbbbbbbbbbbbbbbbb";&nbsp;<br>aaaaaaaaaaa是在运行时刻赋值的；&nbsp;<br>而bbbbbbbbbbb是在编译时就确定的；&nbsp;<br>但是，在以后的存取中，在栈上的数组比指针所指向的字符串(例如堆)快。&nbsp;<br>比如：&nbsp;<br>#include&nbsp;<br>void&nbsp;main()&nbsp;<br>{&nbsp;<br>char&nbsp;a&nbsp;=&nbsp;1;&nbsp;<br>char&nbsp;c[]&nbsp;=&nbsp;"1234567890";&nbsp;<br>char&nbsp;*p&nbsp;="1234567890";&nbsp;<br>a&nbsp;=&nbsp;c[1];&nbsp;<br>a&nbsp;=&nbsp;p[1];&nbsp;<br>return;&nbsp;<br>}&nbsp;<br>对应的汇编代码&nbsp;<br>10:&nbsp;a&nbsp;=&nbsp;c[1];&nbsp;<br>00401067&nbsp;8A&nbsp;4D&nbsp;F1&nbsp;mov&nbsp;cl,byte&nbsp;ptr&nbsp;[ebp-0Fh]&nbsp;<br>0040106A&nbsp;88&nbsp;4D&nbsp;FC&nbsp;mov&nbsp;byte&nbsp;ptr&nbsp;[ebp-4],cl&nbsp;<br>11:&nbsp;a&nbsp;=&nbsp;p[1];&nbsp;<br>0040106D&nbsp;8B&nbsp;55&nbsp;EC&nbsp;mov&nbsp;edx,dword&nbsp;ptr&nbsp;[ebp-14h]&nbsp;<br>00401070&nbsp;8A&nbsp;42&nbsp;01&nbsp;mov&nbsp;al,byte&nbsp;ptr&nbsp;[edx+1]&nbsp;<br>00401073&nbsp;88&nbsp;45&nbsp;FC&nbsp;mov&nbsp;byte&nbsp;ptr&nbsp;[ebp-4],al&nbsp;<br>第一种在读取时直接就把字符串中的元素读到寄存器cl中，而第二种则要先把指针值读到edx中，在根据edx读取字符，显然慢了。&nbsp;</p>
<p><br>2.7小结：&nbsp;<br>堆和栈的区别可以用如下的比喻来看出：&nbsp;<br>使用栈就象我们去饭馆里吃饭，只管点菜（发出申请）、付钱、和吃（使用），吃饱了就走，不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作，他的好处是快捷，但是自由度小。&nbsp;<br>使用堆就象是自己动手做喜欢吃的菜肴，比较麻烦，但是比较符合自己的口味，而且自由度大。&nbsp;<br><br><br><br></p>
<p>windows进程中的内存结构</p>
<p><br>在阅读本文之前，如果你连堆栈是什么多不知道的话，请先阅读文章后面的基础知识。&nbsp;</p>
<p>接触过编程的人都知道，高级语言都能通过变量名来访问内存中的数据。那么这些变量在内存中是如何存放的呢？程序又是如何使用这些变量的呢？下面就会对此进行深入的讨论。下文中的C语言代码如没有特别声明，默认都使用VC编译的release版。&nbsp;</p>
<p>首先，来了解一下&nbsp;C&nbsp;语言的变量是如何在内存分部的。C&nbsp;语言有全局变量(Global)、本地变量(Local)，静态变量(Static)、寄存器变量(Regeister)。每种变量都有不同的分配方式。先来看下面这段代码：&nbsp;</p>
<p>#include&nbsp;&lt;stdio.h&gt;&nbsp;</p>
<p>int&nbsp;g1=0,&nbsp;g2=0,&nbsp;g3=0;&nbsp;</p>
<p>int&nbsp;main()&nbsp;<br>{&nbsp;<br>static&nbsp;int&nbsp;s1=0,&nbsp;s2=0,&nbsp;s3=0;&nbsp;<br>int&nbsp;v1=0,&nbsp;v2=0,&nbsp;v3=0;&nbsp;</p>
<p>//打印出各个变量的内存地址&nbsp;</p>
<p>printf("0x%08x\n",&amp;v1);&nbsp;//打印各本地变量的内存地址&nbsp;<br>printf("0x%08x\n",&amp;v2);&nbsp;<br>printf("0x%08x\n\n",&amp;v3);&nbsp;<br>printf("0x%08x\n",&amp;g1);&nbsp;//打印各全局变量的内存地址&nbsp;<br>printf("0x%08x\n",&amp;g2);&nbsp;<br>printf("0x%08x\n\n",&amp;g3);&nbsp;<br>printf("0x%08x\n",&amp;s1);&nbsp;//打印各静态变量的内存地址&nbsp;<br>printf("0x%08x\n",&amp;s2);&nbsp;<br>printf("0x%08x\n\n",&amp;s3);&nbsp;<br>return&nbsp;0;&nbsp;<br>}&nbsp;</p>
<p>编译后的执行结果是：&nbsp;</p>
<p>0x0012ff78&nbsp;<br>0x0012ff7c&nbsp;<br>0x0012ff80&nbsp;</p>
<p>0x004068d0&nbsp;<br>0x004068d4&nbsp;<br>0x004068d8&nbsp;</p>
<p>0x004068dc&nbsp;<br>0x004068e0&nbsp;<br>0x004068e4&nbsp;</p>
<p>输出的结果就是变量的内存地址。其中v1,v2,v3是本地变量，g1,g2,g3是全局变量，s1,s2,s3是静态变量。你可以看到这些变量在内存是连续分布的，但是本地变量和全局变量分配的内存地址差了十万八千里，而全局变量和静态变量分配的内存是连续的。这是因为本地变量和全局/静态变量是分配在不同类型的内存区域中的结果。对于一个进程的内存空间而言，可以在逻辑上分成3个部份：代码区，静态数据区和动态数据区。动态数据区一般就是&#8220;堆栈&#8221;。&#8220;栈(stack)&#8221;和&#8220;堆(heap)&#8221;是两种不同的动态数据区，栈是一种线性结构，堆是一种链式结构。进程的每个线程都有私有的&#8220;栈&#8221;，所以每个线程虽然代码一样，但本地变量的数据都是互不干扰。一个堆栈可以通过&#8220;基地址&#8221;和&#8220;栈顶&#8221;地址来描述。全局变量和静态变量分配在静态数据区，本地变量分配在动态数据区，即堆栈中。程序通过堆栈的基地址和偏移量来访问本地变量。&nbsp;</p>
<p><br>├———————┤低端内存区域&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;动态数据区&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;代码区&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;静态数据区&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&nbsp;<br>├———————┤高端内存区域&nbsp;</p>
<p><br>堆栈是一个先进后出的数据结构，栈顶地址总是小于等于栈的基地址。我们可以先了解一下函数调用的过程，以便对堆栈在程序中的作用有更深入的了解。不同的语言有不同的函数调用规定，这些因素有参数的压入规则和堆栈的平衡。windows&nbsp;API的调用规则和ANSI&nbsp;C的函数调用规则是不一样的，前者由被调函数调整堆栈，后者由调用者调整堆栈。两者通过&#8220;__stdcall&#8221;和&#8220;__cdecl&#8221;前缀区分。先看下面这段代码：&nbsp;</p>
<p>#include&nbsp;&lt;stdio.h&gt;&nbsp;</p>
<p>void&nbsp;__stdcall&nbsp;func(int&nbsp;param1,int&nbsp;param2,int&nbsp;param3)&nbsp;<br>{&nbsp;<br>int&nbsp;var1=param1;&nbsp;<br>int&nbsp;var2=param2;&nbsp;<br>int&nbsp;var3=param3;&nbsp;<br>printf("0x%08x\n",&#182;m1);&nbsp;//打印出各个变量的内存地址&nbsp;<br>printf("0x%08x\n",&#182;m2);&nbsp;<br>printf("0x%08x\n\n",&#182;m3);&nbsp;<br>printf("0x%08x\n",&amp;var1);&nbsp;<br>printf("0x%08x\n",&amp;var2);&nbsp;<br>printf("0x%08x\n\n",&amp;var3);&nbsp;<br>return;&nbsp;<br>}&nbsp;</p>
<p>int&nbsp;main()&nbsp;<br>{&nbsp;<br>func(1,2,3);&nbsp;<br>return&nbsp;0;&nbsp;<br>}&nbsp;</p>
<p>编译后的执行结果是：&nbsp;</p>
<p>0x0012ff78&nbsp;<br>0x0012ff7c&nbsp;<br>0x0012ff80&nbsp;</p>
<p>0x0012ff68&nbsp;<br>0x0012ff6c&nbsp;<br>0x0012ff70&nbsp;</p>
<p><br>├———————┤&lt;—函数执行时的栈顶（ESP）、低端内存区域&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;var&nbsp;1&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;var&nbsp;2&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;var&nbsp;3&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;RET&nbsp;│&nbsp;<br>├———————┤&lt;—&#8220;__cdecl&#8221;函数返回后的栈顶（ESP）&nbsp;<br>│&nbsp;parameter&nbsp;1&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;parameter&nbsp;2&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;parameter&nbsp;3&nbsp;│&nbsp;<br>├———————┤&lt;—&#8220;__stdcall&#8221;函数返回后的栈顶（ESP）&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&nbsp;<br>├———————┤&lt;—栈底（基地址&nbsp;EBP）、高端内存区域&nbsp;</p>
<p><br>上图就是函数调用过程中堆栈的样子了。首先，三个参数以从又到左的次序压入堆栈，先压&#8220;param3&#8221;，再压&#8220;param2&#8221;，最后压入&#8220;param1&#8221;；然后压入函数的返回地址(RET)，接着跳转到函数地址接着执行（这里要补充一点，介绍UNIX下的缓冲溢出原理的文章中都提到在压入RET后，继续压入当前EBP，然后用当前ESP代替EBP。然而，有一篇介绍windows下函数调用的文章中说，在windows下的函数调用也有这一步骤，但根据我的实际调试，并未发现这一步，这还可以从param3和var1之间只有4字节的间隙这点看出来）；第三步，将栈顶(ESP)减去一个数，为本地变量分配内存空间，上例中是减去12字节(ESP=ESP-3*4，每个int变量占用4个字节)；接着就初始化本地变量的内存空间。由于&#8220;__stdcall&#8221;调用由被调函数调整堆栈，所以在函数返回前要恢复堆栈，先回收本地变量占用的内存(ESP=ESP+3*4)，然后取出返回地址，填入EIP寄存器，回收先前压入参数占用的内存(ESP=ESP+3*4)，继续执行调用者的代码。参见下列汇编代码：&nbsp;</p>
<p>;--------------func&nbsp;函数的汇编代码-------------------&nbsp;</p>
<p>:00401000&nbsp;83EC0C&nbsp;sub&nbsp;esp,&nbsp;0000000C&nbsp;//创建本地变量的内存空间&nbsp;<br>:00401003&nbsp;8B442410&nbsp;mov&nbsp;eax,&nbsp;dword&nbsp;ptr&nbsp;[esp+10]&nbsp;<br>:00401007&nbsp;8B4C2414&nbsp;mov&nbsp;ecx,&nbsp;dword&nbsp;ptr&nbsp;[esp+14]&nbsp;<br>:0040100B&nbsp;8B542418&nbsp;mov&nbsp;edx,&nbsp;dword&nbsp;ptr&nbsp;[esp+18]&nbsp;<br>:0040100F&nbsp;89442400&nbsp;mov&nbsp;dword&nbsp;ptr&nbsp;[esp],&nbsp;eax&nbsp;<br>:00401013&nbsp;8D442410&nbsp;lea&nbsp;eax,&nbsp;dword&nbsp;ptr&nbsp;[esp+10]&nbsp;<br>:00401017&nbsp;894C2404&nbsp;mov&nbsp;dword&nbsp;ptr&nbsp;[esp+04],&nbsp;ecx&nbsp;</p>
<p>&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;（省略若干代码）&nbsp;</p>
<p>:00401075&nbsp;83C43C&nbsp;add&nbsp;esp,&nbsp;0000003C&nbsp;;恢复堆栈，回收本地变量的内存空间&nbsp;<br>:00401078&nbsp;C3&nbsp;ret&nbsp;000C&nbsp;;函数返回，恢复参数占用的内存空间&nbsp;<br>;如果是&#8220;__cdecl&#8221;的话，这里是&#8220;ret&#8221;，堆栈将由调用者恢复&nbsp;</p>
<p>;-------------------函数结束-------------------------&nbsp;</p>
<p><br>;--------------主程序调用func函数的代码--------------&nbsp;</p>
<p>:00401080&nbsp;6A03&nbsp;push&nbsp;00000003&nbsp;//压入参数param3&nbsp;<br>:00401082&nbsp;6A02&nbsp;push&nbsp;00000002&nbsp;//压入参数param2&nbsp;<br>:00401084&nbsp;6A01&nbsp;push&nbsp;00000001&nbsp;//压入参数param1&nbsp;<br>:00401086&nbsp;E875FFFFFF&nbsp;call&nbsp;00401000&nbsp;//调用func函数&nbsp;<br>;如果是&#8220;__cdecl&#8221;的话，将在这里恢复堆栈，&#8220;add&nbsp;esp,&nbsp;0000000C&#8221;&nbsp;</p>
<p>聪明的读者看到这里，差不多就明白缓冲溢出的原理了。先来看下面的代码：&nbsp;</p>
<p>#include&nbsp;&lt;stdio.h&gt;&nbsp;<br>#include&nbsp;&lt;string.h&gt;&nbsp;</p>
<p>void&nbsp;__stdcall&nbsp;func()&nbsp;<br>{&nbsp;<br>char&nbsp;lpBuff[8]="\0";&nbsp;<br>strcat(lpBuff,"AAAAAAAAAAA");&nbsp;<br>return;&nbsp;<br>}&nbsp;</p>
<p>int&nbsp;main()&nbsp;<br>{&nbsp;<br>func();&nbsp;<br>return&nbsp;0;&nbsp;<br>}&nbsp;</p>
<p>编译后执行一下回怎么样？哈，&#8220;"0x00414141"指令引用的"0x00000000"内存。该内存不能为"read"。&#8221;，&#8220;非法操作&#8221;喽！"41"就是"A"的16进制的ASCII码了，那明显就是strcat这句出的问题了。"lpBuff"的大小只有8字节，算进结尾的\0，那strcat最多只能写入7个"A"，但程序实际写入了11个"A"外加1个\0。再来看看上面那幅图，多出来的4个字节正好覆盖了RET的所在的内存空间，导致函数返回到一个错误的内存地址，执行了错误的指令。如果能精心构造这个字符串，使它分成三部分，前一部份仅仅是填充的无意义数据以达到溢出的目的，接着是一个覆盖RET的数据，紧接着是一段shellcode，那只要着个RET地址能指向这段shellcode的第一个指令，那函数返回时就能执行shellcode了。但是软件的不同版本和不同的运行环境都可能影响这段shellcode在内存中的位置，那么要构造这个RET是十分困难的。一般都在RET和shellcode之间填充大量的NOP指令，使得exploit有更强的通用性。&nbsp;</p>
<p><br>├———————┤&lt;—低端内存区域&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&nbsp;<br>├———————┤&lt;—由exploit填入数据的开始&nbsp;<br>│&nbsp;│&nbsp;<br>│&nbsp;buffer&nbsp;│&lt;—填入无用的数据&nbsp;<br>│&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;RET&nbsp;│&lt;—指向shellcode，或NOP指令的范围&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;NOP&nbsp;│&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&lt;—填入的NOP指令，是RET可指向的范围&nbsp;<br>│&nbsp;NOP&nbsp;│&nbsp;<br>├———————┤&nbsp;<br>│&nbsp;│&nbsp;<br>│&nbsp;shellcode&nbsp;│&nbsp;<br>│&nbsp;│&nbsp;<br>├———————┤&lt;—由exploit填入数据的结束&nbsp;<br>│&nbsp;&#8230;&#8230;&nbsp;│&nbsp;<br>├———————┤&lt;—高端内存区域&nbsp;</p>
<p><br>windows下的动态数据除了可存放在栈中，还可以存放在堆中。了解C++的朋友都知道，C++可以使用new关键字来动态分配内存。来看下面的C++代码：&nbsp;</p>
<p>#include&nbsp;&lt;stdio.h&gt;&nbsp;<br>#include&nbsp;&lt;iostream.h&gt;&nbsp;<br>#include&nbsp;&lt;windows.h&gt;&nbsp;</p>
<p>void&nbsp;func()&nbsp;<br>{&nbsp;<br>char&nbsp;*buffer=new&nbsp;char[128];&nbsp;<br>char&nbsp;bufflocal[128];&nbsp;<br>static&nbsp;char&nbsp;buffstatic[128];&nbsp;<br>printf("0x%08x\n",buffer);&nbsp;//打印堆中变量的内存地址&nbsp;<br>printf("0x%08x\n",bufflocal);&nbsp;//打印本地变量的内存地址&nbsp;<br>printf("0x%08x\n",buffstatic);&nbsp;//打印静态变量的内存地址&nbsp;<br>}&nbsp;</p>
<p>void&nbsp;main()&nbsp;<br>{&nbsp;<br>func();&nbsp;<br>return;&nbsp;<br>}&nbsp;</p>
<p>程序执行结果为：&nbsp;</p>
<p>0x004107d0&nbsp;<br>0x0012ff04&nbsp;<br>0x004068c0&nbsp;</p>
<p>可以发现用new关键字分配的内存即不在栈中，也不在静态数据区。VC编译器是通过windows下的&#8220;堆(heap)&#8221;来实现new关键字的内存动态分配。在讲&#8220;堆&#8221;之前，先来了解一下和&#8220;堆&#8221;有关的几个API函数：&nbsp;</p>
<p>HeapAlloc&nbsp;在堆中申请内存空间&nbsp;<br>HeapCreate&nbsp;创建一个新的堆对象&nbsp;<br>HeapDestroy&nbsp;销毁一个堆对象&nbsp;<br>HeapFree&nbsp;释放申请的内存&nbsp;<br>HeapWalk&nbsp;枚举堆对象的所有内存块&nbsp;<br>GetProcessHeap&nbsp;取得进程的默认堆对象&nbsp;<br>GetProcessHeaps&nbsp;取得进程所有的堆对象&nbsp;<br>LocalAlloc&nbsp;<br>GlobalAlloc&nbsp;</p>
<p>当进程初始化时，系统会自动为进程创建一个默认堆，这个堆默认所占内存的大小为1M。堆对象由系统进行管理，它在内存中以链式结构存在。通过下面的代码可以通过堆动态申请内存空间：&nbsp;</p>
<p>HANDLE&nbsp;hHeap=GetProcessHeap();&nbsp;<br>char&nbsp;*buff=HeapAlloc(hHeap,0,8);&nbsp;</p>
<p>其中hHeap是堆对象的句柄，buff是指向申请的内存空间的地址。那这个hHeap究竟是什么呢？它的值有什么意义吗？看看下面这段代码吧：&nbsp;</p>
<p>#pragma&nbsp;comment(linker,"/entry:main")&nbsp;//定义程序的入口&nbsp;<br>#include&nbsp;&lt;windows.h&gt;&nbsp;</p>
<p>_CRTIMP&nbsp;int&nbsp;(__cdecl&nbsp;*printf)(const&nbsp;char&nbsp;*,&nbsp;...);&nbsp;//定义STL函数printf&nbsp;<br>/*---------------------------------------------------------------------------&nbsp;<br>写到这里，我们顺便来复习一下前面所讲的知识：&nbsp;<br>(*注)printf函数是C语言的标准函数库中函数，VC的标准函数库由msvcrt.dll模块实现。&nbsp;<br>由函数定义可见，printf的参数个数是可变的，函数内部无法预先知道调用者压入的参数个数，函数只能通过分析第一个参数字符串的格式来获得压入参数的信息，由于这里参数的个数是动态的，所以必须由调用者来平衡堆栈，这里便使用了__cdecl调用规则。BTW，Windows系统的API函数基本上是__stdcall调用形式，只有一个API例外，那就是wsprintf，它使用__cdecl调用规则，同printf函数一样，这是由于它的参数个数是可变的缘故。&nbsp;<br>---------------------------------------------------------------------------*/&nbsp;<br>void&nbsp;main()&nbsp;<br>{&nbsp;<br>HANDLE&nbsp;hHeap=GetProcessHeap();&nbsp;<br>char&nbsp;*buff=HeapAlloc(hHeap,0,0x10);&nbsp;<br>char&nbsp;*buff2=HeapAlloc(hHeap,0,0x10);&nbsp;<br>HMODULE&nbsp;hMsvcrt=LoadLibrary("msvcrt.dll");&nbsp;<br>printf=(void&nbsp;*)GetProcAddress(hMsvcrt,"printf");&nbsp;<br>printf("0x%08x\n",hHeap);&nbsp;<br>printf("0x%08x\n",buff);&nbsp;<br>printf("0x%08x\n\n",buff2);&nbsp;<br>}&nbsp;</p>
<p>执行结果为：&nbsp;</p>
<p>0x00130000&nbsp;<br>0x00133100&nbsp;<br>0x00133118&nbsp;</p>
<p>hHeap的值怎么和那个buff的值那么接近呢？其实hHeap这个句柄就是指向HEAP首部的地址。在进程的用户区存着一个叫PEB(进程环境块)的结构，这个结构中存放着一些有关进程的重要信息，其中在PEB首地址偏移0x18处存放的ProcessHeap就是进程默认堆的地址，而偏移0x90处存放了指向进程所有堆的地址列表的指针。windows有很多API都使用进程的默认堆来存放动态数据，如windows&nbsp;2000下的所有ANSI版本的函数都是在默认堆中申请内存来转换ANSI字符串到Unicode字符串的。对一个堆的访问是顺序进行的，同一时刻只能有一个线程访问堆中的数据，当多个线程同时有访问要求时，只能排队等待，这样便造成程序执行效率下降。&nbsp;</p>
<p>最后来说说内存中的数据对齐。所位数据对齐，是指数据所在的内存地址必须是该数据长度的整数倍，DWORD数据的内存起始地址能被4除尽，WORD数据的内存起始地址能被2除尽，x86&nbsp;CPU能直接访问对齐的数据，当他试图访问一个未对齐的数据时，会在内部进行一系列的调整，这些调整对于程序来说是透明的，但是会降低运行速度，所以编译器在编译程序时会尽量保证数据对齐。同样一段代码，我们来看看用VC、Dev-C++和lcc三个不同编译器编译出来的程序的执行结果：&nbsp;</p>
<p>#include&nbsp;&lt;stdio.h&gt;&nbsp;</p>
<p>int&nbsp;main()&nbsp;<br>{&nbsp;<br>int&nbsp;a;&nbsp;<br>char&nbsp;b;&nbsp;<br>int&nbsp;c;&nbsp;<br>printf("0x%08x\n",&amp;a);&nbsp;<br>printf("0x%08x\n",&amp;b);&nbsp;<br>printf("0x%08x\n",&amp;c);&nbsp;<br>return&nbsp;0;&nbsp;<br>}&nbsp;</p>
<p>这是用VC编译后的执行结果：&nbsp;<br>0x0012ff7c&nbsp;<br>0x0012ff7b&nbsp;<br>0x0012ff80&nbsp;<br>变量在内存中的顺序：b(1字节)-a(4字节)-c(4字节)。&nbsp;</p>
<p>这是用Dev-C++编译后的执行结果：&nbsp;<br>0x0022ff7c&nbsp;<br>0x0022ff7b&nbsp;<br>0x0022ff74&nbsp;<br>变量在内存中的顺序：c(4字节)-中间相隔3字节-b(占1字节)-a(4字节)。&nbsp;</p>
<p>这是用lcc编译后的执行结果：&nbsp;<br>0x0012ff6c&nbsp;<br>0x0012ff6b&nbsp;<br>0x0012ff64&nbsp;<br>变量在内存中的顺序：同上。&nbsp;</p>
<p>三个编译器都做到了数据对齐，但是后两个编译器显然没VC&#8220;聪明&#8221;，让一个char占了4字节，浪费内存哦。&nbsp;</p>
<p><br>基础知识：&nbsp;<br>堆栈是一种简单的数据结构，是一种只允许在其一端进行插入或删除的线性表。允许插入或删除操作的一端称为栈顶，另一端称为栈底，对堆栈的插入和删除操作被称为入栈和出栈。有一组CPU指令可以实现对进程的内存实现堆栈访问。其中，POP指令实现出栈操作，PUSH指令实现入栈操作。CPU的ESP寄存器存放当前线程的栈顶指针，EBP寄存器中保存当前线程的栈底指针。CPU的EIP寄存器存放下一个CPU指令存放的内存地址，当CPU执行完当前的指令后，从EIP寄存器中读取下一条指令的内存地址，然后继续执行。&nbsp;</p>
<p><br>参考：《Windows下的HEAP溢出及其利用》by:&nbsp;isno&nbsp;<br>《windows核心编程》by:&nbsp;Jeffrey&nbsp;Richter&nbsp;<br><br><br><br></p>
<p>摘要：&nbsp;讨论常见的堆性能问题以及如何防范它们。（共&nbsp;9&nbsp;页）</p>
<p>前言<br>您是否是动态分配的&nbsp;C/C++&nbsp;对象忠实且幸运的用户？您是否在模块间的往返通信中频繁地使用了&#8220;自动化&#8221;？您的程序是否因堆分配而运行起来很慢？不仅仅您遇到这样的问题。几乎所有项目迟早都会遇到堆问题。大家都想说，&#8220;我的代码真正好，只是堆太慢&#8221;。那只是部分正确。更深入理解堆及其用法、以及会发生什么问题，是很有用的。</p>
<p>什么是堆？<br>（如果您已经知道什么是堆，可以跳到&#8220;什么是常见的堆性能问题？&#8221;部分）</p>
<p>在程序中，使用堆来动态分配和释放对象。在下列情况下，调用堆操作：&nbsp;</p>
<p>事先不知道程序所需对象的数量和大小。</p>
<p><br>对象太大而不适合堆栈分配程序。<br>堆使用了在运行时分配给代码和堆栈的内存之外的部分内存。下图给出了堆分配程序的不同层。<br><br><img src="http://www.cppblog.com/images/cppblog_com/mzty/4364/o_staackheap.gif" border=0><br><a href="http://club.5ivb.net/UploadFile/2005311144027byUID16686.gif" target=_blank></a></p>
<p>GlobalAlloc/GlobalFree：Microsoft&nbsp;Win32&nbsp;堆调用，这些调用直接与每个进程的默认堆进行对话。</p>
<p>LocalAlloc/LocalFree：Win32&nbsp;堆调用（为了与&nbsp;Microsoft&nbsp;Windows&nbsp;NT&nbsp;兼容），这些调用直接与每个进程的默认堆进行对话。</p>
<p>COM&nbsp;的&nbsp;IMalloc&nbsp;分配程序（或&nbsp;CoTaskMemAlloc&nbsp;/&nbsp;CoTaskMemFree）：函数使用每个进程的默认堆。自动化程序使用&#8220;组件对象模型&nbsp;(COM)&#8221;的分配程序，而申请的程序使用每个进程堆。</p>
<p>C/C++&nbsp;运行时&nbsp;(CRT)&nbsp;分配程序：提供了&nbsp;malloc()&nbsp;和&nbsp;free()&nbsp;以及&nbsp;new&nbsp;和&nbsp;delete&nbsp;操作符。如&nbsp;Microsoft&nbsp;Visual&nbsp;Basic&nbsp;和&nbsp;Java&nbsp;等语言也提供了新的操作符并使用垃圾收集来代替堆。CRT&nbsp;创建自己的私有堆，驻留在&nbsp;Win32&nbsp;堆的顶部。</p>
<p>Windows&nbsp;NT&nbsp;中，Win32&nbsp;堆是&nbsp;Windows&nbsp;NT&nbsp;运行时分配程序周围的薄层。所有&nbsp;API&nbsp;转发它们的请求给&nbsp;NTDLL。</p>
<p>Windows&nbsp;NT&nbsp;运行时分配程序提供&nbsp;Windows&nbsp;NT&nbsp;内的核心堆分配程序。它由具有&nbsp;128&nbsp;个大小从&nbsp;8&nbsp;到&nbsp;1,024&nbsp;字节的空闲列表的前端分配程序组成。后端分配程序使用虚拟内存来保留和提交页。</p>
<p>在图表的底部是&#8220;虚拟内存分配程序&#8221;，操作系统使用它来保留和提交页。所有分配程序使用虚拟内存进行数据的存取。</p>
<p>分配和释放块不就那么简单吗？为何花费这么长时间？</p>
<p>堆实现的注意事项<br>传统上，操作系统和运行时库是与堆的实现共存的。在一个进程的开始，操作系统创建一个默认堆，叫做&#8220;进程堆&#8221;。如果没有其他堆可使用，则块的分配使用&#8220;进程堆&#8221;。语言运行时也能在进程内创建单独的堆。（例如，C&nbsp;运行时创建它自己的堆。）除这些专用的堆外，应用程序或许多已载入的动态链接库&nbsp;(DLL)&nbsp;之一可以创建和使用单独的堆。Win32&nbsp;提供一整套&nbsp;API&nbsp;来创建和使用私有堆。有关堆函数（英文）的详尽指导，请参见&nbsp;MSDN。</p>
<p>当应用程序或&nbsp;DLL&nbsp;创建私有堆时，这些堆存在于进程空间，并且在进程内是可访问的。从给定堆分配的数据将在同一个堆上释放。（不能从一个堆分配而在另一个堆释放。）</p>
<p>在所有虚拟内存系统中，堆驻留在操作系统的&#8220;虚拟内存管理器&#8221;的顶部。语言运行时堆也驻留在虚拟内存顶部。某些情况下，这些堆是操作系统堆中的层，而语言运行时堆则通过大块的分配来执行自己的内存管理。不使用操作系统堆，而使用虚拟内存函数更利于堆的分配和块的使用。</p>
<p>典型的堆实现由前、后端分配程序组成。前端分配程序维持固定大小块的空闲列表。对于一次分配调用，堆尝试从前端列表找到一个自由块。如果失败，堆被迫从后端（保留和提交虚拟内存）分配一个大块来满足请求。通用的实现有每块分配的开销，这将耗费执行周期，也减少了可使用的存储空间。</p>
<p>Knowledge&nbsp;Base&nbsp;文章&nbsp;Q10758，&#8220;用&nbsp;calloc()&nbsp;和&nbsp;malloc()&nbsp;管理内存&#8221;&nbsp;（搜索文章编号）,&nbsp;包含了有关这些主题的更多背景知识。另外，有关堆实现和设计的详细讨论也可在下列著作中找到：&#8220;Dynamic&nbsp;Storage&nbsp;Allocation:&nbsp;A&nbsp;Survey&nbsp;and&nbsp;Critical&nbsp;Review&#8221;，作者&nbsp;Paul&nbsp;R.&nbsp;Wilson、Mark&nbsp;S.&nbsp;Johnstone、Michael&nbsp;Neely&nbsp;和&nbsp;David&nbsp;Boles；&#8220;International&nbsp;Workshop&nbsp;on&nbsp;Memory&nbsp;Management&#8221;,&nbsp;作者&nbsp;Kinross,&nbsp;Scotland,&nbsp;UK,&nbsp;1995&nbsp;年&nbsp;9&nbsp;月(<img src="http://club.5ivb.net/pic/url.gif" align=absMiddle border=0><a href="http://www.cs.utexas.edu/users/oops/papers.html" target=_blank><font color=#000000><u>http://www.cs.utexas.edu/users/oops/papers.html</u></font></a>)（英文）。</p>
<p>Windows&nbsp;NT&nbsp;的实现（Windows&nbsp;NT&nbsp;版本&nbsp;4.0&nbsp;和更新版本）&nbsp;使用了&nbsp;127&nbsp;个大小从&nbsp;8&nbsp;到&nbsp;1,024&nbsp;字节的&nbsp;8&nbsp;字节对齐块空闲列表和一个&#8220;大块&#8221;列表。&#8220;大块&#8221;列表（空闲列表[0]）&nbsp;保存大于&nbsp;1,024&nbsp;字节的块。空闲列表容纳了用双向链表链接在一起的对象。默认情况下，&#8220;进程堆&#8221;执行收集操作。（收集是将相邻空闲块合并成一个大块的操作。）收集耗费了额外的周期，但减少了堆块的内部碎片。</p>
<p>单一全局锁保护堆，防止多线程式的使用。（请参见&#8220;Server&nbsp;Performance&nbsp;and&nbsp;Scalability&nbsp;Killers&#8221;中的第一个注意事项,&nbsp;George&nbsp;Reilly&nbsp;所著，在&nbsp;&#8220;MSDN&nbsp;Online&nbsp;Web&nbsp;Workshop&#8221;上（站点：<img src="http://club.5ivb.net/pic/url.gif" align=absMiddle border=0><a href="http://msdn.microsoft.com/workshop/server/iis/tencom.asp" target=_blank><font color=#000000><u>http://msdn.microsoft.com/workshop/server/iis/tencom.asp</u></font></a>（英文）。）单一全局锁本质上是用来保护堆数据结构，防止跨多线程的随机存取。若堆操作太频繁，单一全局锁会对性能有不利的影响。</p>
<p>什么是常见的堆性能问题？<br>以下是您使用堆时会遇到的最常见问题：&nbsp;</p>
<p>分配操作造成的速度减慢。光分配就耗费很长时间。最可能导致运行速度减慢原因是空闲列表没有块，所以运行时分配程序代码会耗费周期寻找较大的空闲块，或从后端分配程序分配新块。</p>
<p><br>释放操作造成的速度减慢。释放操作耗费较多周期，主要是启用了收集操作。收集期间，每个释放操作&#8220;查找&#8221;它的相邻块，取出它们并构造成较大块，然后再把此较大块插入空闲列表。在查找期间，内存可能会随机碰到，从而导致高速缓存不能命中，性能降低。</p>
<p><br>堆竞争造成的速度减慢。当两个或多个线程同时访问数据，而且一个线程继续进行之前必须等待另一个线程完成时就发生竞争。竞争总是导致麻烦；这也是目前多处理器系统遇到的最大问题。当大量使用内存块的应用程序或&nbsp;DLL&nbsp;以多线程方式运行（或运行于多处理器系统上）时将导致速度减慢。单一锁定的使用—常用的解决方案—意味着使用堆的所有操作是序列化的。当等待锁定时序列化会引起线程切换上下文。可以想象交叉路口闪烁的红灯处走走停停导致的速度减慢。&nbsp;<br>竞争通常会导致线程和进程的上下文切换。上下文切换的开销是很大的，但开销更大的是数据从处理器高速缓存中丢失，以及后来线程复活时的数据重建。</p>
<p>堆破坏造成的速度减慢。造成堆破坏的原因是应用程序对堆块的不正确使用。通常情形包括释放已释放的堆块或使用已释放的堆块，以及块的越界重写等明显问题。（破坏不在本文讨论范围之内。有关内存重写和泄漏等其他细节，请参见&nbsp;Microsoft&nbsp;Visual&nbsp;C++(R)&nbsp;调试文档&nbsp;。）</p>
<p><br>频繁的分配和重分配造成的速度减慢。这是使用脚本语言时非常普遍的现象。如字符串被反复分配，随重分配增长和释放。不要这样做，如果可能，尽量分配大字符串和使用缓冲区。另一种方法就是尽量少用连接操作。<br>竞争是在分配和释放操作中导致速度减慢的问题。理想情况下，希望使用没有竞争和快速分配/释放的堆。可惜，现在还没有这样的通用堆，也许将来会有。</p>
<p>在所有的服务器系统中（如&nbsp;IIS、MSProxy、DatabaseStacks、网络服务器、&nbsp;Exchange&nbsp;和其他）,&nbsp;堆锁定实在是个大瓶颈。处理器数越多，竞争就越会恶化。</p>
<p>尽量减少堆的使用<br>现在您明白使用堆时存在的问题了，难道您不想拥有能解决这些问题的超级魔棒吗？我可希望有。但没有魔法能使堆运行加快—因此不要期望在产品出货之前的最后一星期能够大为改观。如果提前规划堆策略，情况将会大大好转。调整使用堆的方法，减少对堆的操作是提高性能的良方。</p>
<p>如何减少使用堆操作？通过利用数据结构内的位置可减少堆操作的次数。请考虑下列实例：</p>
<p>struct&nbsp;ObjectA&nbsp;{<br>&nbsp;&nbsp;&nbsp;//&nbsp;objectA&nbsp;的数据&nbsp;<br>}</p>
<p>struct&nbsp;ObjectB&nbsp;{<br>&nbsp;&nbsp;&nbsp;//&nbsp;objectB&nbsp;的数据&nbsp;<br>}</p>
<p>//&nbsp;同时使用&nbsp;objectA&nbsp;和&nbsp;objectB</p>
<p>//<br>//&nbsp;使用指针&nbsp;<br>//<br>struct&nbsp;ObjectB&nbsp;{<br>&nbsp;&nbsp;&nbsp;struct&nbsp;ObjectA&nbsp;*&nbsp;pObjA;<br>&nbsp;&nbsp;&nbsp;//&nbsp;objectB&nbsp;的数据&nbsp;<br>}</p>
<p>//<br>//&nbsp;使用嵌入<br>//<br>struct&nbsp;ObjectB&nbsp;{<br>&nbsp;&nbsp;&nbsp;struct&nbsp;ObjectA&nbsp;pObjA;<br>&nbsp;&nbsp;&nbsp;//&nbsp;objectB&nbsp;的数据&nbsp;<br>}</p>
<p>//<br>//&nbsp;集合&nbsp;&#8211;&nbsp;在另一对象内使用&nbsp;objectA&nbsp;和&nbsp;objectB<br>//</p>
<p>struct&nbsp;ObjectX&nbsp;{<br>&nbsp;&nbsp;&nbsp;struct&nbsp;ObjectA&nbsp;&nbsp;objA;<br>&nbsp;&nbsp;&nbsp;struct&nbsp;ObjectB&nbsp;&nbsp;objB;<br>}</p>
<p>避免使用指针关联两个数据结构。如果使用指针关联两个数据结构，前面实例中的对象&nbsp;A&nbsp;和&nbsp;B&nbsp;将被分别分配和释放。这会增加额外开销—我们要避免这种做法。</p>
<p><br>把带指针的子对象嵌入父对象。当对象中有指针时，则意味着对象中有动态元素（百分之八十）和没有引用的新位置。嵌入增加了位置从而减少了进一步分配/释放的需求。这将提高应用程序的性能。</p>
<p><br>合并小对象形成大对象（聚合）。聚合减少分配和释放的块的数量。如果有几个开发者，各自开发设计的不同部分，则最终会有许多小对象需要合并。集成的挑战就是要找到正确的聚合边界。</p>
<p><br>内联缓冲区能够满足百分之八十的需要（aka&nbsp;80-20&nbsp;规则）。个别情况下，需要内存缓冲区来保存字符串/二进制数据，但事先不知道总字节数。估计并内联一个大小能满足百分之八十需要的缓冲区。对剩余的百分之二十，可以分配一个新的缓冲区和指向这个缓冲区的指针。这样，就减少分配和释放调用并增加数据的位置空间，从根本上提高代码的性能。</p>
<p><br>在块中分配对象（块化）。块化是以组的方式一次分配多个对象的方法。如果对列表的项连续跟踪，例如对一个&nbsp;{名称，值}&nbsp;对的列表，有两种选择：选择一是为每一个&#8220;名称-值&#8221;对分配一个节点；选择二是分配一个能容纳（如五个）&#8220;名称-值&#8221;对的结构。例如，一般情况下，如果存储四对，就可减少节点的数量，如果需要额外的空间数量，则使用附加的链表指针。&nbsp;<br>块化是友好的处理器高速缓存，特别是对于&nbsp;L1-高速缓存，因为它提供了增加的位置&nbsp;—不用说对于块分配，很多数据块会在同一个虚拟页中。</p>
<p>正确使用&nbsp;_amblksiz。C&nbsp;运行时&nbsp;(CRT)&nbsp;有它的自定义前端分配程序，该分配程序从后端（Win32&nbsp;堆）分配大小为&nbsp;_amblksiz&nbsp;的块。将&nbsp;_amblksiz&nbsp;设置为较高的值能潜在地减少对后端的调用次数。这只对广泛使用&nbsp;CRT&nbsp;的程序适用。<br>使用上述技术将获得的好处会因对象类型、大小及工作量而有所不同。但总能在性能和可升缩性方面有所收获。另一方面，代码会有点特殊，但如果经过深思熟虑，代码还是很容易管理的。</p>
<p>其他提高性能的技术<br>下面是一些提高速度的技术：&nbsp;</p>
<p>使用&nbsp;Windows&nbsp;NT5&nbsp;堆&nbsp;<br>由于几个同事的努力和辛勤工作，1998&nbsp;年初&nbsp;Microsoft&nbsp;Windows(R)&nbsp;2000&nbsp;中有了几个重大改进：</p>
<p>改进了堆代码内的锁定。堆代码对每堆一个锁。全局锁保护堆数据结构，防止多线程式的使用。但不幸的是，在高通信量的情况下，堆仍受困于全局锁，导致高竞争和低性能。Windows&nbsp;2000&nbsp;中，锁内代码的临界区将竞争的可能性减到最小,从而提高了可伸缩性。</p>
<p><br>使用&nbsp;&#8220;Lookaside&#8221;列表。堆数据结构对块的所有空闲项使用了大小在&nbsp;8&nbsp;到&nbsp;1,024&nbsp;字节（以&nbsp;8-字节递增）的快速高速缓存。快速高速缓存最初保护在全局锁内。现在，使用&nbsp;lookaside&nbsp;列表来访问这些快速高速缓存空闲列表。这些列表不要求锁定，而是使用&nbsp;64&nbsp;位的互锁操作，因此提高了性能。</p>
<p><br>内部数据结构算法也得到改进。<br>这些改进避免了对分配高速缓存的需求，但不排除其他的优化。使用&nbsp;Windows&nbsp;NT5&nbsp;堆评估您的代码；它对小于&nbsp;1,024&nbsp;字节&nbsp;(1&nbsp;KB)&nbsp;的块（来自前端分配程序的块）是最佳的。GlobalAlloc()&nbsp;和&nbsp;LocalAlloc()&nbsp;建立在同一堆上，是存取每个进程堆的通用机制。如果希望获得高的局部性能，则使用&nbsp;Heap(R)&nbsp;API&nbsp;来存取每个进程堆，或为分配操作创建自己的堆。如果需要对大块操作，也可以直接使用&nbsp;VirtualAlloc()&nbsp;/&nbsp;VirtualFree()&nbsp;操作。</p>
<p>上述改进已在&nbsp;Windows&nbsp;2000&nbsp;beta&nbsp;2&nbsp;和&nbsp;Windows&nbsp;NT&nbsp;4.0&nbsp;SP4&nbsp;中使用。改进后，堆锁的竞争率显著降低。这使所有&nbsp;Win32&nbsp;堆的直接用户受益。CRT&nbsp;堆建立于&nbsp;Win32&nbsp;堆的顶部，但它使用自己的小块堆，因而不能从&nbsp;Windows&nbsp;NT&nbsp;改进中受益。（Visual&nbsp;C++&nbsp;版本&nbsp;6.0&nbsp;也有改进的堆分配程序。）</p>
<p>使用分配高速缓存&nbsp;<br>分配高速缓存允许高速缓存分配的块，以便将来重用。这能够减少对进程堆（或全局堆）的分配/释放调用的次数，也允许最大限度的重用曾经分配的块。另外，分配高速缓存允许收集统计信息,以便较好地理解对象在较高层次上的使用。</p>
<p>典型地，自定义堆分配程序在进程堆的顶部实现。自定义堆分配程序与系统堆的行为很相似。主要的差别是它在进程堆的顶部为分配的对象提供高速缓存。高速缓存设计成一套固定大小（如&nbsp;32&nbsp;字节、64&nbsp;字节、128&nbsp;字节等）。这一个很好的策略，但这种自定义堆分配程序丢失与分配和释放的对象相关的&#8220;语义信息&#8221;。&nbsp;</p>
<p>与自定义堆分配程序相反，&#8220;分配高速缓存&#8221;作为每类分配高速缓存来实现。除能够提供自定义堆分配程序的所有好处之外，它们还能够保留大量语义信息。每个分配高速缓存处理程序与一个目标二进制对象关联。它能够使用一套参数进行初始化，这些参数表示并发级别、对象大小和保持在空闲列表中的元素的数量等。分配高速缓存处理程序对象维持自己的私有空闲实体池（不超过指定的阀值）并使用私有保护锁。合在一起，分配高速缓存和私有锁减少了与主系统堆的通信量，因而提供了增加的并发、最大限度的重用和较高的可伸缩性。</p>
<p>需要使用清理程序来定期检查所有分配高速缓存处理程序的活动情况并回收未用的资源。如果发现没有活动，将释放分配对象的池，从而提高性能。</p>
<p>可以审核每个分配/释放活动。第一级信息包括对象、分配和释放调用的总数。通过查看它们的统计信息可以得出各个对象之间的语义关系。利用以上介绍的许多技术之一，这种关系可以用来减少内存分配。</p>
<p>分配高速缓存也起到了调试助手的作用，帮助您跟踪没有完全清除的对象数量。通过查看动态堆栈返回踪迹和除没有清除的对象之外的签名，甚至能够找到确切的失败的调用者。</p>
<p>MP&nbsp;堆&nbsp;<br>MP&nbsp;堆是对多处理器友好的分布式分配的程序包，在&nbsp;Win32&nbsp;SDK（Windows&nbsp;NT&nbsp;4.0&nbsp;和更新版本）中可以得到。最初由&nbsp;JVert&nbsp;实现，此处堆抽象建立在&nbsp;Win32&nbsp;堆程序包的顶部。MP&nbsp;堆创建多个&nbsp;Win32&nbsp;堆，并试图将分配调用分布到不同堆，以减少在所有单一锁上的竞争。</p>
<p>本程序包是好的步骤&nbsp;—一种改进的&nbsp;MP-友好的自定义堆分配程序。但是，它不提供语义信息和缺乏统计功能。通常将&nbsp;MP&nbsp;堆作为&nbsp;SDK&nbsp;库来使用。如果使用这个&nbsp;SDK&nbsp;创建可重用组件，您将大大受益。但是，如果在每个&nbsp;DLL&nbsp;中建立这个&nbsp;SDK&nbsp;库，将增加工作设置。</p>
<p>重新思考算法和数据结构&nbsp;<br>要在多处理器机器上伸缩，则算法、实现、数据结构和硬件必须动态伸缩。请看最经常分配和释放的数据结构。试问，&#8220;我能用不同的数据结构完成此工作吗？&#8221;例如，如果在应用程序初始化时加载了只读项的列表，这个列表不必是线性链接的列表。如果是动态分配的数组就非常好。动态分配的数组将减少内存中的堆块和碎片，从而增强性能。</p>
<p>减少需要的小对象的数量减少堆分配程序的负载。例如，我们在服务器的关键处理路径上使用五个不同的对象，每个对象单独分配和释放。一起高速缓存这些对象，把堆调用从五个减少到一个，显著减少了堆的负载，特别当每秒钟处理&nbsp;1,000&nbsp;个以上的请求时。</p>
<p>如果大量使用&#8220;Automation&#8221;结构，请考虑从主线代码中删除&#8220;Automation&nbsp;BSTR&#8221;，或至少避免重复的&nbsp;BSTR&nbsp;操作。（BSTR&nbsp;连接导致过多的重分配和分配/释放操作。）</p>
<p>摘要<br>对所有平台往往都存在堆实现，因此有巨大的开销。每个单独代码都有特定的要求，但设计能采用本文讨论的基本理论来减少堆之间的相互作用。&nbsp;</p>
<p>评价您的代码中堆的使用。</p>
<p><br>改进您的代码，以使用较少的堆调用：分析关键路径和固定数据结构。</p>
<p><br>在实现自定义的包装程序之前使用量化堆调用成本的方法。</p>
<p><br>如果对性能不满意，请要求&nbsp;OS&nbsp;组改进堆。更多这类请求意味着对改进堆的更多关注。</p>
<p><br>要求&nbsp;C&nbsp;运行时组针对&nbsp;OS&nbsp;所提供的堆制作小巧的分配包装程序。随着&nbsp;OS&nbsp;堆的改进，C&nbsp;运行时堆调用的成本将减小。</p>
<p><br>操作系统（Windows&nbsp;NT&nbsp;家族）正在不断改进堆。请随时关注和利用这些改进。<br>Murali&nbsp;Krishnan&nbsp;是&nbsp;Internet&nbsp;Information&nbsp;Server&nbsp;(IIS)&nbsp;组的首席软件设计工程师。从&nbsp;1.0&nbsp;版本开始他就设计&nbsp;IIS，并成功发行了&nbsp;1.0&nbsp;版本到&nbsp;4.0&nbsp;版本。Murali&nbsp;组织并领导&nbsp;IIS&nbsp;性能组三年&nbsp;(1995-1998),&nbsp;从一开始就影响&nbsp;IIS&nbsp;性能。他拥有威斯康星州&nbsp;Madison&nbsp;大学的&nbsp;M.S.和印度&nbsp;Anna&nbsp;大学的&nbsp;B.S.。工作之外，他喜欢阅读、打排球和家庭烹饪。<br><br><br><br><img src="http://club.5ivb.net/pic/url.gif" align=absMiddle border=0><a href="http://community.csdn.net/Expert/FAQ/FAQ_Index.asp?id=172835" target=_blank><font color=#000000><u>http://community.csdn.net/Expert/FAQ/FAQ_Index.asp?id=172835</u></font></a><br>我在学习对象的生存方式的时候见到一种是在堆栈(stack)之中，如下&nbsp;&nbsp;<br>CObject&nbsp;&nbsp;object;&nbsp;&nbsp;<br>还有一种是在堆(heap)中&nbsp;&nbsp;如下&nbsp;&nbsp;<br>CObject*&nbsp;&nbsp;pobject=new&nbsp;&nbsp;CObject();&nbsp;&nbsp;<br>&nbsp;<br>请问&nbsp;&nbsp;<br>（1）这两种方式有什么区别？&nbsp;&nbsp;<br>（2）堆栈与堆有什么区别？？&nbsp;&nbsp;<br>&nbsp;<br>&nbsp;<br>---------------------------------------------------------------&nbsp;&nbsp;<br>&nbsp;<br>1)&nbsp;&nbsp;about&nbsp;&nbsp;stack,&nbsp;&nbsp;system&nbsp;&nbsp;will&nbsp;&nbsp;allocate&nbsp;&nbsp;memory&nbsp;&nbsp;to&nbsp;&nbsp;the&nbsp;&nbsp;instance&nbsp;&nbsp;of&nbsp;&nbsp;object&nbsp;&nbsp;automatically,&nbsp;&nbsp;and&nbsp;&nbsp;to&nbsp;&nbsp;the <br>&nbsp;heap,&nbsp;&nbsp;you&nbsp;&nbsp;must&nbsp;&nbsp;allocate&nbsp;&nbsp;memory&nbsp;&nbsp;to&nbsp;&nbsp;the&nbsp;&nbsp;instance&nbsp;&nbsp;of&nbsp;&nbsp;object&nbsp;&nbsp;with&nbsp;&nbsp;new&nbsp;&nbsp;or&nbsp;&nbsp;malloc&nbsp;&nbsp;manually.&nbsp;&nbsp;<br>2)&nbsp;&nbsp;when&nbsp;&nbsp;function&nbsp;&nbsp;ends,&nbsp;&nbsp;system&nbsp;&nbsp;will&nbsp;&nbsp;automatically&nbsp;&nbsp;free&nbsp;&nbsp;the&nbsp;&nbsp;memory&nbsp;&nbsp;area&nbsp;&nbsp;of&nbsp;&nbsp;stack,&nbsp;&nbsp;but&nbsp;&nbsp;to&nbsp;&nbsp;the&nbsp; <br>heap,&nbsp;&nbsp;you&nbsp;&nbsp;must&nbsp;&nbsp;free&nbsp;&nbsp;the&nbsp;&nbsp;memory&nbsp;&nbsp;area&nbsp;&nbsp;manually&nbsp;&nbsp;with&nbsp;&nbsp;free&nbsp;&nbsp;or&nbsp;&nbsp;delete,&nbsp;&nbsp;else&nbsp;&nbsp;it&nbsp;&nbsp;will&nbsp;&nbsp;result&nbsp;&nbsp;in&nbsp;&nbsp;memory <br>leak.&nbsp;&nbsp;<br>3)栈内存分配运算内置于处理器的指令集中，效率很高，但是分配的内存容量有限。&nbsp;&nbsp;<br>4）堆上分配的内存可以有我们自己决定，使用非常灵活。&nbsp;&nbsp;<br>---------------------------------------------------------------&nbsp;&nbsp;</p>
</div>
</div>
<div class=postbody>&nbsp;</div><img src ="http://www.cppblog.com/mzty/aggbug/37679.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-12-03 13:36 <a href="http://www.cppblog.com/mzty/archive/2007/12/03/37679.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>引领boost（六）（boost::bind）</title><link>http://www.cppblog.com/mzty/archive/2007/09/05/31622.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Wed, 05 Sep 2007 06:40:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/09/05/31622.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/31622.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/09/05/31622.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/31622.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/31622.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;Boost::bind一 Boost::bind&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 在STL中，我们经常需要使用bind1st，bind2st函数绑定器和fun_ptr,mem_fun等函数适配器，这些函数绑定器和函数适配器使用起来比较麻烦，需要根据是全局函数还是类的成员函数，是一个参数还是多个参数等做出不同的选择，而且有些情况使用STL提供的不...&nbsp;&nbsp;<a href='http://www.cppblog.com/mzty/archive/2007/09/05/31622.html'>阅读全文</a><img src ="http://www.cppblog.com/mzty/aggbug/31622.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-09-05 14:40 <a href="http://www.cppblog.com/mzty/archive/2007/09/05/31622.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>引领Boost（五）（Boost::array）</title><link>http://www.cppblog.com/mzty/archive/2007/08/24/30775.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Fri, 24 Aug 2007 09:49:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/08/24/30775.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/30775.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/08/24/30775.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/30775.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/30775.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Boost::array一 Boost::array&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 在以前，如果我们要处理一组数据，我们可能使用一般数组存储，或者需要许多的对数组的数据的操作的时候，我们使用STL容器存储。但是如果我们的需求是，我们能够提前固定一组数据的大小，或提前知道这组数据的大小，但是我们又想这组数据进行一些操作，比如排序。。。显然对这个情况，上面的...&nbsp;&nbsp;<a href='http://www.cppblog.com/mzty/archive/2007/08/24/30775.html'>阅读全文</a><img src ="http://www.cppblog.com/mzty/aggbug/30775.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-08-24 17:49 <a href="http://www.cppblog.com/mzty/archive/2007/08/24/30775.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>引领Boost（四）（Boost::smart_ptr）</title><link>http://www.cppblog.com/mzty/archive/2007/08/22/30611.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Wed, 22 Aug 2007 09:27:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/08/22/30611.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/30611.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/08/22/30611.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/30611.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/30611.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Boost::smart_ptr一 Boost::smart_Ptr&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 我们学习C++都知道智能指针，例如STL中的std::auto_ptr，但是为什么要使用智能指针，使用它能带给我们什么好处呢？&nbsp;&nbsp;&nbsp; 最简单的使用智能指针可以不会因为忘记delete指针而造成内存泄露。还有如果我们开发或者...&nbsp;&nbsp;<a href='http://www.cppblog.com/mzty/archive/2007/08/22/30611.html'>阅读全文</a><img src ="http://www.cppblog.com/mzty/aggbug/30611.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-08-22 17:27 <a href="http://www.cppblog.com/mzty/archive/2007/08/22/30611.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>引领Boost（三）（Boost::tuple）</title><link>http://www.cppblog.com/mzty/archive/2007/08/21/30509.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Tue, 21 Aug 2007 06:04:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/08/21/30509.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/30509.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/08/21/30509.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/30509.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/30509.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Boost::tuple一 Boost::tuple&nbsp;&nbsp;&nbsp; 很多的时候我们经常需要为我们的函数返回多个值，一般的做法是通过传入非常量的指针或引用，但是这样的话可能可读性就要差一些，使用者可能需要确切的文档才能确定到底哪个是返回值，为了更好的可读性，我们可以使用class或struct来封装我们要返回的多个值，然后返回封装struct或class，但是使用这种方...&nbsp;&nbsp;<a href='http://www.cppblog.com/mzty/archive/2007/08/21/30509.html'>阅读全文</a><img src ="http://www.cppblog.com/mzty/aggbug/30509.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-08-21 14:04 <a href="http://www.cppblog.com/mzty/archive/2007/08/21/30509.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>引领Boost（二）（Boost::Any）</title><link>http://www.cppblog.com/mzty/archive/2007/08/16/30156.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Thu, 16 Aug 2007 08:28:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/08/16/30156.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/30156.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/08/16/30156.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/30156.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/30156.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Boost::Any一 Boost::Any&nbsp;&nbsp;&nbsp; 很多时候我们想有一种可以代表任何类型的类型，比如像纯面向对象语言java或.net中的Object类型，但是对于C++本身并没有这样一个基类，所以我们如果要解决这类问题，首先我们考虑的是使用基类的指针，这能够解决以部分问题，但是更多的我们可以求助于void*，使用void*的缺点就是丢失了类型信息和缺乏类型安...&nbsp;&nbsp;<a href='http://www.cppblog.com/mzty/archive/2007/08/16/30156.html'>阅读全文</a><img src ="http://www.cppblog.com/mzty/aggbug/30156.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-08-16 16:28 <a href="http://www.cppblog.com/mzty/archive/2007/08/16/30156.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>引领Boost（一）（开篇）</title><link>http://www.cppblog.com/mzty/archive/2007/08/15/30095.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Wed, 15 Aug 2007 10:19:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/08/15/30095.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/30095.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/08/15/30095.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/30095.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/30095.html</trackback:ping><description><![CDATA[<p>引领boost（开篇）</p>
<p>一BOOST</p>
<p>Boost带领你远远地超越了C++标准库，它使得C++编程更优雅、更有活力、更高产。（引自：Beyond the C++ Standard Library: An Introduction to Boost）（慢慢体会哦！）</p>
<p>二参考</p>
<p>主要：</p>
<p>boost的在线document：<a href="http://boost.org/libs/libraries.htm">http://boost.org/libs/libraries.htm</a></p>
<p>唯一的关于boost的book：Beyond the C++ Standard Library: An Introduction to Boost</p>
<p>其他：</p>
<p><a href="http://www.boost.org/">http://www.boost.org/</a></p>
<p>heroboy2000:&nbsp;&nbsp; <a href="http://blog.csdn.net/heroboy2000/">http://blog.csdn.net/heroboy2000/</a><br>dozb:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://dozb.bokee.com/catalog_2005.html">http://dozb.bokee.com/catalog_2005.html</a></p>
<p>boost china:&nbsp;&nbsp; <a href="http://www.stlchina.org/twiki/bin/view.pl/Main/BoostChina">http://www.stlchina.org/twiki/bin/view.pl/Main/BoostChina</a></p>
<br>三 boost库索引（来自boost china）（本系列文章使用boost 1.34版本）<br><br>
<h4><a name="2.0 字符串和文本处理( String and"></a>2.0 字符串和文本处理( String and text processing) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/conversion/lexical_cast.htm"><u><font color=#0000ff>conversion/lexical_cast</font></u></a> - <tt>lexical_cast</tt> 类模板，作者 Kevlin Henney.
    <li><a href="http://www.boost.org/libs/format/index.html"><u><font color=#0000ff>format</font></u></a> - 类型安全的 '类似printf' 格式的操作, 作者 Samuel Krempp.
    <li><a href="http://www.boost.org/libs/regex/index.html"><u><font color=#0000ff>regex</font></u></a> - 正则表达式库, 作者 John Maddock .
    <li><a href="http://www.boost.org/libs/spirit/index.html"><u><font color=#0000ff>spirit</font></u></a> - LL分析的框架，在嵌入式C++中根据EBNF规则对文件进行分析, 作者 Joel de Guzman and team.
    <li><a href="http://www.boost.org/libs/tokenizer/index.html"><u><font color=#0000ff>tokenizer</font></u></a> - 把字符串或其他字符序列分解成一系列标记(tokens), 作者 John Bandela.
    <li><a href="http://www.boost.org/libs/algorithm/string/index.html"><u><font color=#0000ff>string_algo</font></u></a> - 字符串算法库, 作者 Pavol Droba . </li>
</ul>
<h4><a name="2.1 容器(Containers)"></a>2.1 容器(Containers) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/array/index.html"><u><font color=#0000ff>array</font></u></a> - STL风格封装下的定长数组, 作者 Nicolai Josuttis.
    <li><a href="http://www.boost.org/libs/dynamic_bitset/dynamic_bitset.html"><u><font color=#800080>dynamic_bitset</font></u></a> - <tt>std::bitset</tt>的动态长度版本, 作者 Jeremy Siek 和 Chuck Allison.
    <li><a href="http://www.boost.org/libs/graph/doc/table_of_contents.html"><u><font color=#0000ff>graph</font></u></a> - 泛型图的组件和算法, 作者 Jeremy Siek 和 a University of Notre Dame team.
    <li><a href="http://www.boost.org/libs/multi_array/doc/index.html"><u><font color=#0000ff>multi_array</font></u></a> - 多维数组的容器和配接器, 作者 Ron Garcia.
    <li><a href="http://www.boost.org/libs/multi_index/doc/index.html"><u><font color=#0000ff>multi_index</font></u></a> - 提供对可重复键值STL兼容容器的存取接口, 作者 Joaqu&#237;n M L&#243;pez Mu&#241;oz.
    <li><a href="http://www.boost.org/libs/property_map/property_map.html"><u><font color=#0000ff>property map</font></u></a> - Concepts defining interfaces which map key objects to value objects, 作者 Jeremy Siek.
    <li><a href="http://www.boost.org/libs/variant/index.html"><u><font color=#0000ff>variant</font></u></a> - 安全, 泛型, 基于栈的，不同于联合容器, 作者 Eric Friedman and Itay Maman. </li>
</ul>
<h4><a name="2.2 迭代器(Iterators)"></a>2.2 迭代器(Iterators) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/graph/doc/table_of_contents.html"><u><font color=#0000ff>graph</font></u></a> - 泛型图的组件和算法, 作者 Jeremy Siek 和 a University of Notre Dame team.&nbsp;
    <li><a href="http://www.boost.org/libs/iterator/doc/index.html"><u><font color=#0000ff>iterators</font></u></a> - Iterator 构造框架, 配接器, 概念, 和其他, 作者 Dave Abrahams, Jeremy Siek, 和 Thomas Witt.
    <li><a href="http://www.boost.org/libs/utility/operators.htm"><u><font color=#0000ff>operators</font></u></a> - 使算法类和迭代器容易的模板, 作者 Dave Abrahams 和 Jeremy Siek.
    <li><a href="http://www.boost.org/libs/tokenizer/index.html"><u><font color=#0000ff>tokenizer</font></u></a> - 把字符串或其他字符序列分解成一系列标记(tokens), 作者 John Bandela. </li>
</ul>
<h4><a name="2.3 算法( Algorithms )"></a>2.3 算法( Algorithms ) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/graph/doc/table_of_contents.html"><u><font color=#0000ff>graph</font></u></a> - 泛型图的组件和算法, 作者 Jeremy Siek 和 a University of Notre Dame team.&nbsp;
    <li><a href="http://www.boost.org/libs/algorithm/minmax/index.html"><u><font color=#0000ff>minmax</font></u></a> - 标准库扩展，用于同时进行 min/max 和 min/max 元素计算, 作者 Herv&#233; Br&#246;nnimann.
    <li><a href="http://www.boost.org/libs/algorithm/string/index.html"><u><font color=#0000ff>string_algo</font></u></a> - 字符串算法库, 作者 Pavol Droba .
    <li><a href="http://www.boost.org/libs/utility/utility.htm"><u><font color=#0000ff>utility</font></u></a> - 类 <strong>next(),</strong>&nbsp; <strong>prior()</strong> 函数模板, 作者 Dave Abrahams and others.
    <li><a href="http://www.boost.org/libs/range/index.html"><u><font color=#0000ff>range</font></u></a> - new 根基，其为建于new iterator概念之上的泛型计算, 作者 Thorsten Ottosen. </li>
</ul>
<h4><a name="2.4 函数对象和高阶编程(Function"></a><a name="2.4 函数对象和高阶编程(Function "></a>2.4 函数对象和高阶编程(Function objects and higher-order programming) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/bind/bind.html"><u><font color=#0000ff>bind</font></u></a> 和 <a href="http://www.boost.org/libs/bind/mem_fn.html"><u><font color=#0000ff>mem_fn</font></u></a> - 为函数/对象/指针和成员函数而被泛化的组合者, 作者 Peter Dimov.
    <li><a href="http://www.boost.org/libs/function/index.html"><u><font color=#0000ff>function</font></u></a> - 为延期调用和回调的函数对象的包裹, 作者 Doug Gregor.
    <li><a href="http://www.boost.org/libs/functional/index.html"><u><font color=#0000ff>functional</font></u></a> - 增强的函数对象配接器, 作者 Mark Rodgers.
    <li><a href="http://www.boost.org/libs/lambda/index.html"><u><font color=#0000ff>lambda</font></u></a> - 在实际调用地点定义小的无名函数对象, 作者 Jaakko J&#228;rvi 和 Gary Powell.
    <li><a href="http://www.boost.org/libs/bind/ref.html"><u><font color=#0000ff>ref</font></u></a> - 一个工具库，用于传递引用到泛型函数, 作者 Jaako J&#228;rvi, Peter Dimov, Doug Gregor, 和 Dave Abrahams.
    <li><a href="http://www.boost.org/libs/signals/index.html"><u><font color=#0000ff>signals</font></u></a> - 被管理的信号和邮槽回调的实现, 作者 Doug Gregor.
    <li><a href="http://www.boost.org/libs/utility/utility.htm#result_of"><u><font color=#0000ff>result_of</font></u></a> - 确定函数调用表达式的类型. </li>
</ul>
<h4><a name="2.5 泛型编程(Generic Programming"></a>2.5 泛型编程(Generic Programming) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/utility/call_traits.htm"><u><font color=#0000ff>call_traits</font></u></a> - 实现自动判断传入参数的方式, 作者 John Maddock, Howard Hinnant, et al.
    <li><a href="http://www.boost.org/libs/concept_check/concept_check.htm"><u><font color=#0000ff>concept check</font></u></a> - 泛型编程的工具, 作者 Jeremy Siek.
    <li><a href="http://www.boost.org/libs/utility/enable_if.html"><u><font color=#0000ff>enable_if</font></u></a> - 函数模板重载时的选择性包含, 作者 Jaakko J&#228;rvi, Jeremiah Willcock, 和 Andrew Lumsdaine.
    <li><a href="http://www.boost.org/libs/utility/in_place_factories.html"><u><font color=#0000ff>in_place_factory, typed_in_place_factory</font></u></a>- Generic in-place construction of contained objects with a variadic argument-list, 作者 Fernando Cacciola.
    <li><a href="http://www.boost.org/libs/utility/operators.htm"><u><font color=#0000ff>operators</font></u></a> - 使算法类和迭代器容易的模板, 作者 Dave Abrahams 和 Jeremy Siek.
    <li><a href="http://www.boost.org/libs/property_map/property_map.html"><u><font color=#0000ff>property map</font></u></a> - Concepts defining interfaces which map key objects to value objects, 作者 Jeremy Siek.
    <li><a href="http://www.boost.org/libs/static_assert/static_assert.htm"><u><font color=#0000ff>static_assert</font></u></a> - 静态断言 (编译时断言), 作者 John Maddock.
    <li><a href="http://www.boost.org/libs/type_traits/index.html"><u><font color=#0000ff>type_traits</font></u></a> - 类型的基本属性的模板, 作者 John Maddock, Steve Cleary, et al. </li>
</ul>
<h4><a name="2.6 模板元编程(Template Metaprog"></a>2.6 模板元编程(Template Metaprogramming ) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/mpl/doc/index.html"><u><font color=#0000ff>mpl</font></u></a> - 模板元编程框架，用于编译时计算，序列化和元函数类, 作者 Aleksey Gurtovoy.
    <li><a href="http://www.boost.org/libs/static_assert/static_assert.htm"><u><font color=#0000ff>static_assert</font></u></a> - 静态断言 (编译时断言), 作者 John Maddock.
    <li><a href="http://www.boost.org/libs/type_traits/index.html"><u><font color=#0000ff>type_traits</font></u></a> - 类型的基本属性的模板, 作者 John Maddock, Steve Cleary, et al. </li>
</ul>
<h4><a name="2.7 预处理元编程(Preprocessor Me"></a>2.7 预处理元编程(Preprocessor Metaprogramming) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/preprocessor/doc/index.html"><u><font color=#0000ff>preprocessor</font></u></a> - 预处理元编程工具，包含重复和递归, 作者 Vesa Karvonen 和 Paul Mensonides. </li>
</ul>
<h4><a name="2.8 并发编程(Concurrent Programm"></a>2.8 并发编程(Concurrent Programming) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/thread/doc/index.html"><u><font color=#0000ff>thread</font></u></a> - 轻便的C++多线程库, 作者 William Kempf. </li>
</ul>
<h4><a name="2.9 数学和数值计算(Math and nume"></a>2.9 数学和数值计算(Math and numerics) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/math/doc/index.html"><u><font color=#0000ff>math</font></u></a> - 在数学领域的几个贡献, 作者 various authors.
    <li><a href="http://www.boost.org/libs/conversion/cast.htm"><u><font color=#0000ff>conversion/numeric_cast</font></u></a> - <tt>numeric_cast</tt> 类模板, 作者 Kevlin Henney.
    <li><a href="http://www.boost.org/libs/numeric/conversion/index.html"><u><font color=#0000ff>numeric/conversion</font></u></a> - 优化的基于策略的数值变换, 作者 Fernando Cacciola.
    <li><a href="http://www.boost.org/libs/integer/index.html"><u><font color=#0000ff>integer</font></u></a> - 能够帮助简化对整数类型的处理。
    <li><a href="http://www.boost.org/libs/numeric/interval/doc/interval.htm"><u><font color=#0000ff>interval </font></u></a>- Extends the usual arithmetic functions to mathematical intervals, 作者 Guillaume Melquiond, Herv&#233; Br&#246;nnimann and Sylvain Pion.
    <li><a href="http://www.boost.org/libs/math/doc/common_factor.html"><u><font color=#0000ff>math/common_factor</font></u></a> - 最大公约数和最小公倍数, 作者 Daryle Walker.
    <li><a href="http://www.boost.org/libs/math/octonion/index.html"><u><font color=#0000ff>math/octonion</font></u></a> - Octonions, 作者 Hubert Holin.
    <li><a href="http://www.boost.org/libs/math/quaternion/index.html"><u><font color=#0000ff>math/quaternion</font></u></a> - Quaternions, 作者 Hubert Holin.
    <li><a href="http://www.boost.org/libs/math/special_functions/index.html"><u><font color=#0000ff>math/special_functions</font></u></a> - 数学方面的函数比如 atanh, sinc, 和 sinhc, 作者 Hubert Holin.
    <li><a href="http://www.boost.org/libs/multi_array/doc/index.html"><u><font color=#0000ff>multi_array</font></u></a> - 多维数组的容器和配接器, 作者 Ron Garcia.
    <li><a href="http://www.boost.org/libs/utility/operators.htm"><u><font color=#0000ff>operators</font></u></a> - 使算法类和迭代器容易的模板, 作者 Dave Abrahams 和 Jeremy Siek.
    <li><a href="http://www.boost.org/libs/random/index.html"><u><font color=#0000ff>random</font></u></a> - 随机数生成的完整系统, 作者 Jens Maurer.
    <li><a href="http://www.boost.org/libs/rational/index.html"><u><font color=#0000ff>rational</font></u></a> - 有理数类, 作者 Paul Moore.
    <li><a href="http://www.boost.org/libs/numeric/ublas/doc/index.htm"><u><font color=#0000ff>uBLAS</font></u></a> - 基本线性代数，用于矩阵操作, 作者 Joerg Walter and Mathias Koch. </li>
</ul>
<h4><a name="2.10 纠错和测试( Correctness and"></a>2.10 纠错和测试( Correctness and testing) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/concept_check/concept_check.htm"><u><font color=#0000ff>concept check</font></u></a> - 泛型编程的工具, 作者 Jeremy Siek.
    <li><a href="http://www.boost.org/libs/static_assert/static_assert.htm"><u><font color=#0000ff>static_assert</font></u></a> - 静态断言 (编译时断言), 作者 John Maddock.
    <li><a href="http://www.boost.org/libs/test/doc/index.html"><u><font color=#0000ff>test</font></u></a> - 支持简单程序测试, 完整单元测试, 和程序执行监控, 作者 Gennadiy Rozental. </li>
</ul>
<h4><a name="2.11数据结构( Data structures)"></a>2.11数据结构( Data structures) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/any/index.html"><u><font color=#800080>any</font></u></a> - 安全，泛型的容器，包含不同类型的值, 作者 Kevlin Henney.
    <li><a href="http://www.boost.org/libs/utility/compressed_pair.htm"><u><font color=#0000ff>compressed_pair</font></u></a> - 针对pair当中空成员做了一些优化, 作者 John Maddock, Howard Hinnant, et al.
    <li><a href="http://www.boost.org/libs/multi_index/doc/index.html"><u><font color=#0000ff>multi_index</font></u></a> - 提供对可重复键值STL兼容容器的存取接口, 作者 Joaqu&#237;n M L&#243;pez Mu&#241;oz.
    <li><a href="http://www.boost.org/libs/tuple/doc/tuple_users_guide.html"><u><font color=#0000ff>tuple</font></u></a> - 容易地定义可返回多个值的函数, 作者 Jaakko J&#228;rvi.
    <li><a href="http://www.boost.org/libs/variant/index.html"><u><font color=#0000ff>variant</font></u></a> - 安全, 泛型, 基于栈的，不同于联合容器, 作者 Eric Friedman and Itay Maman. </li>
</ul>
<h4><a name="2.12 输入/输出(Input/Output)"></a>2.12 输入/输出(Input/Output) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/format/index.html"><u><font color=#0000ff>format</font></u></a> - 类型安全的 '类似printf' 格式的操作, 作者 Samuel Krempp.
    <li><a href="http://www.boost.org/libs/io/doc/ios_state.html"><u><font color=#0000ff>io state savers</font></u></a> - 保存 I/O 状态来防止混乱的数据, 作者 Daryle Walker.
    <li><a href="http://www.boost.org/doc/html/program_options.html"><u><font color=#0000ff>program_options</font></u></a> - 通过命令行，配置文件和其他来源来存取配置参数, 作者 Vladimir Prus.
    <li><a href="http://www.boost.org/libs/serialization/doc/index.html"><u><font color=#0000ff>serialization</font></u></a> - Serialization of arbitrary data for persistence and marshalling, 作者 Robert Ramey
    <li><a href="http://www.boost.org/libs/assign/index.html"><u><font color=#0000ff>assign</font></u></a> - 用常数或更容易方式生成的数据填充容器, 作者 Thorsten Ottosen. </li>
</ul>
<h4><a name="2.13 跨语言支持(Inter-language s"></a>2.13 跨语言支持(Inter-language support) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/python/doc/index.html"><u><font color=#0000ff>python</font></u></a> - 映射 C++ 类和函数给 <a href="http://www.python.org/"><u><font color=#0000ff>Python</font></u></a> 使用， 作者 Dave Abrahams. </li>
</ul>
<h4><a name="2.14 内存(Memory)"></a>2.14 内存(Memory) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/pool/doc/index.html"><u><font color=#0000ff>pool</font></u></a> - 内存池管理, 作者 Steve Cleary.
    <li><a href="http://www.boost.org/libs/smart_ptr/index.html"><u><font color=#0000ff>smart_ptr</font></u></a> - 五个智能指针类模板, 作者 Greg Colvin, Beman Dawes, Peter Dimov, 和 Darin Adler.
    <li><a href="http://www.boost.org/libs/utility/utility.htm"><u><font color=#0000ff>utility</font></u></a> - 类 <strong>noncopyable</strong> 加 <strong>checked_delete()</strong>, <strong>checked_array_delete()</strong>, <strong>next(),</strong>&nbsp; <strong>prior()</strong> 函数模板, 加 <strong>base-from-member idiom</strong>, 作者 Dave Abrahams 等. </li>
</ul>
<h4><a name="2.15解析( Parsing )"></a>2.15解析( Parsing ) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/spirit/index.html"><u><font color=#0000ff>spirit</font></u></a> - LL分析的框架，在嵌入式C++中根据EBNF规则对文件进行分析, 作者 Joel de Guzman and team. </li>
</ul>
<h4><a name="2.16杂项( Miscellaneous )"></a>2.16杂项( Miscellaneous ) </h4>
<ul>
    <li><a href="http://www.boost.org/libs/utility/base_from_member.html"><u><font color=#0000ff>base-from-member</font></u></a> - Idiom to initialize a base class with a member, 作者 Daryle Walker.
    <li><a href="http://www.boost.org/libs/utility/compressed_pair.htm"><u><font color=#0000ff>compressed_pair</font></u></a> - 针对pair当中空成员做了一些优化, 作者 John Maddock, Howard Hinnant, et al.
    <li><a href="http://www.boost.org/libs/conversion/index.html"><u><font color=#0000ff>conversion</font></u></a> - 各种类型间的转化，Numeric, polymorphic, 和 lexical casts, 作者 Dave Abrahams and Kevlin Henney.
    <li><a href="http://www.boost.org/libs/numeric/conversion/index.html"><u><font color=#0000ff>numeric/conversion</font></u></a> - 优化的基于策略的数值变换, 作者 Fernando Cacciola.
    <li><a href="http://www.boost.org/libs/crc/index.html"><u><font color=#0000ff>crc</font></u></a> - 循环沉余码, 作者 Daryle Walker.
    <li><a href="http://www.boost.org/libs/date_time/doc/index.html"><u><font color=#0000ff>date_time</font></u></a> - Date-Time 库， 作者 Jeff Garland.
    <li><a href="http://www.boost.org/libs/filesystem/doc/index.htm"><u><font color=#800080>filesystem</font></u></a> - 方便地操作文件路径, 通过iteration访问目录, 和其他有用的文件系统操作, 作者 Beman Dawes.
    <li><a href="http://www.boost.org/libs/optional/doc/optional.html"><u><font color=#0000ff>optional</font></u></a> - 对可选项值的可识别联合包裹, 作者 Fernando Cacciola.
    <li><a href="http://www.boost.org/doc/html/program_options.html"><u><font color=#0000ff>program_options</font></u></a> - 通过命令行，配置文件和其他来源来存取配置参数, 作者 Vladimir Prus.
    <li><a href="http://www.boost.org/libs/timer/index.html"><u><font color=#0000ff>timer</font></u></a> - 事件定时器, 进度定时器, 和进度显示类, 作者 Beman Dawes.
    <li><a href="http://www.boost.org/doc/html/tribool.html"><u><font color=#0000ff>tribool</font></u></a> - 3种状态的 boolean 类型库, 作者 Doug Gregor.
    <li><a href="http://www.boost.org/libs/utility/utility.htm"><u><font color=#0000ff>utility</font></u></a> - 类 <strong>noncopyable</strong> 加 <strong>checked_delete()</strong>, <strong>checked_array_delete()</strong>, <strong>next(),</strong>&nbsp; <strong>prior()</strong> 函数模板, 加 <strong>base-from-member idiom</strong>, 作者 Dave Abrahams 等.
    <li><a href="http://www.boost.org/libs/utility/value_init.htm"><u><font color=#0000ff>value_initialized</font></u></a> - 为统一的语法的值初始化的包裹, 作者 Fernando Cacciola, 基于 David Abrahams 的思想. </li>
</ul>
<h4><a name="2.17 Broken compiler workarounds"></a>2.17 Broken compiler workarounds </h4>
<ul>
    <li><a href="http://www.boost.org/libs/compatibility/index.html"><u><font color=#0000ff>compatibility</font></u></a> - 对不一致的标准库提供帮助, 作者 Ralf Grosse-Kunstleve and Jens Maurer.
    <li><a href="http://www.boost.org/libs/config/config.htm"><u><font color=#0000ff>config</font></u></a> - 帮助 boost 库的开发者配置编译器特性；不打算提供给库用户使用. </li>
</ul>
<p>&nbsp;</p><img src ="http://www.cppblog.com/mzty/aggbug/30095.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-08-15 18:19 <a href="http://www.cppblog.com/mzty/archive/2007/08/15/30095.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tiny xml使用</title><link>http://www.cppblog.com/mzty/archive/2007/08/15/30057.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Wed, 15 Aug 2007 02:28:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/08/15/30057.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/30057.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/08/15/30057.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/30057.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/30057.html</trackback:ping><description><![CDATA[<p>转自张老师博客：<a href="http://www.cppblog.com/alantop/archive/2006/05/17/7303.html">http://www.cppblog.com/alantop/archive/2006/05/17/7303.html</a><br><br>Homepage: <a href="http://www.grinninglizard.com/tinyxml/">http://www.grinninglizard.com/tinyxml/</a><br>download：<a href="http://sourceforge.net/projects/tinyxml">http://sourceforge.net/projects/tinyxml</a></p>
<p>用mingw32-make前修改一下makefile文件,改为如下：</p>
<p># DEBUG can be set to YES to include debugging info, or NO otherwise(不是DEBUG)<br>DEBUG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; := NO </p>
<p># PROFILE can be set to YES to include profiling info, or NO otherwise<br>PROFILE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; := NO</p>
<p># TINYXML_USE_STL can be used to turn on STL support. NO, then STL<br># will not be used. YES will include the STL files.(使用STL,选择的话，则可以使用std::string)<br>TINYXML_USE_STL := YES</p>
<p>&nbsp;</p>
<p>一、TinyXml的特点 </p>
<p>TinyXml是一个基于DOM模型的、非验证的轻量级C++解释器。</p>
<p>1.SAX和DOM </p>
<p>目前XML的解析主要有两大模型：SAX和DOM。</p>
<p>其中SAX是基于事件的，其基本工作流程是分析XML文档，当发现了一个新的元素时，产生一个对应事件，并调用相应的用户处理函数。这种方式占用内存少，速度快，但用户程序相应得会比较复杂。</p>
<p>而DOM（文档对象模型），则是在分析时，一次性的将整个XML文档进行分析，并在内存中形成对应的树结构，同时，向用户提供一系列的接口来访问和编辑该树结构。这种方式占用内存大，速度往往慢于SAX，但可以给用户提供一个面向对象的访问接口，对用户更为友好。</p>
<p><br>2.验证和非验证 </p>
<p>对于一个特定的XML文档而言，其正确性分为两个层次。首先是其格式应该符合XML的基本格式要求，比如第一行要有声明，标签的嵌套层次必须前后一致等等，符合这些要求的文件，就是一个合格的XML文件，称作well-formatted。但除此之外，一个XML文档因其内容的不同还必须在语义上符合相应的标准，这些标准由相应的DTD文件或者Schema文件来定义，符合了这些定义要求的XML文件，称作valid。</p>
<p>因此，解析器也分为两种，一种是验证的，即会跟据XML文件中的声明，用相应的DTD文件对XML文件进行校验，检查它是否满足DTD文件的要求。另一种是忽略DTD文件，只要基本格式正确，就可以进行解析。</p>
<p>就我所知，验证的解析器通常都是比较重量级的。TinyXml不支持验证，但是体积很小，用在解析格式较为简单的XML文件，比如配置文件时，特别的合适。</p>
<p><br>二、TinyXml的构建和使用<br>1.获取 </p>
<p>TinyXml首页在<a href="http://www.grinninglizard.com/tinyxml/index.html">http://www.grinninglizard.com/tinyxml/index.html</a>，从这里可以找到最新版本的源代码，目前的版本是 2.4.3 (截至2006.5.17).</p>
<p>2.构建 </p>
<p>TinyXml在构建时可以选择是否支持STL，选择的话，则可以使用std::string，所以通常应在Windows上，TinyXml的源码包里提供了VC6的工程文件，直接用它就可以生成两个静该打开这个选项。态库（带STL和不带STL），非常容易。唯一需要注意的是，默认生成的库是单线程的，如果用在多线程的项目中，需要改动一下配置，生成相应的多线程库。</p>
<p>在Unix平台上，TinyXml的源码包里只提供了一个Makefile，对于典型的Linux系统，或装了gcc和gmake的其他Unix，这个Makefile足够用了，我在RH9和RHEL4上测试，简单的make就成功了。需要注意的有以下几点：默认的编译是不支持STL的，可以通过编辑Makefile的TINYXML_USE_STL := NO那一行，把NO改成YES就可以支持STL了；还有默认只生成了一个测试程序，没有生成任何库，如果要生成静态库的话，可以用ar命令，将生成的几个目标文件打包就行了，如果要生成动态库，则需要加上-fpic参数重新编译。</p>
<p>3.使用 </p>
<p>构建了相应的库之后，在使用了它们的工程中，只要在连接时把他们连上就行了。需要注意的是，如果需要STL支持，在编译用到了TinyXml的文件时，需要定义一个宏TIXML_USE_STL，对gcc，可以使用参数-DTIXML_USE_STL，对cl.exe（VC），可以使用参数/DTIXML_USE_STL，如果嫌麻烦，可以直接定义在 tinyxml.h文件里。</p>
<p><br>也可以把需要的源文件加入到我们的project中，向使用自己的文件一样的调用，一般为了更加方便使用，可以对库根据我们实际的数据结构进行再分装。</p>
<p><br>三、TinyXml的编程模型</p>
<p>1.类之间的关系 </p>
<p>TinyXml实现的时DOM访问模型，因此提供了一系列的类对应XML文件中的各个节点。主要类间的关系如下图所示：</p>
<p>TiXmlBase：其它类的基类，是个抽象类</p>
<p>TiXmlNode：表示一个节点，包含节点的一般方法，如访问自节点、兄弟节点、编辑自身、编辑子节点</p>
<p>TiXmlDocument：表示整个XML文档，不对应其中某个特定的节点。</p>
<p>TiXmlElement：表示元素节点，可以包含子节点和TiXmlAttribute</p>
<p>TiXmlComment：表示注释</p>
<p>TiXmlDeclaration：表示声明</p>
<p>TiXmlText：表示文本节点</p>
<p>TiXmlUnknown：表示未知节点，通常是出错了</p>
<p>TiXmlAttribute：表示一个元素的属性</p>
<p>下面是一个简单的例子：</p>
<p>&lt;?xml version="1.0" encoding="utf-8" ?&gt; <br>&lt;!-This is only a sample--&gt; <br>&lt;book&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;TinyXml How To&lt;/name&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;price unit=&#8221;RMB&#8221;&gt;20&lt;/price&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;description&gt;Some words&#8230;&lt;/description&gt; <br>&lt;/ book &gt; </p>
<p><br>整个文档，对应TiXmlDocument</p>
<p>book,name,price, description，都对应TiXmlElement</p>
<p>第一行对应一个TiXmlDeclaration</p>
<p>第二行对应一个TiXmlComment</p>
<p>&#8220;TinyXml How To&#8221;对应一个TiXmlText</p>
<p>unit则是price的一个TiXmlAttribute</p>
<p>这些类与XML文件中的相应元素都有很好的对应关系，因此相信参照TinyXml的文档，可以很容易的掌握各个方法的使用。</p>
<p><br>2.需要注意的问题 </p>
<p>各类之间的转换 <br>由于各个节点类都从TiXmlNode继承，在使用时常常需要将TiXmlNode*类型的指针转换为其派生类的指针，在进行这种转换时，应该首先使用由TiXmlNode类提供的一系列转换函数，如ToElement(void)，而不是c++的dynamic_cast</p>
<p><br>检查返回值 <br>由于TinyXml是一个非校验的解析器，因此当解析一个文件时，很可能文件并不包含我们预期的某个节点，在这种情况下，TinyXml将返回空指针。因此，必须要对返回值进行检查，否则将很容易出现内存访问的错误。</p>
<p><br>如何重头建立一个XML文件 <br>先建立一个TiXmlDocument对象，然后，载入某个模板，或者直接插入一个节点作为根节点，接着就可以像打开一个已有的XML文件那样对它进行操作了。</p>
<p><br>四、总结 </p>
<p>TinyXml最大的特点就是它很小，可以很方便的静态连接到程序里。对于像配置文件、简单的数据文件这类文件的解析，它很适合。但是由于它是非验证的，因此需要在程序里做许多检查工做，加重了程序编写的负担。因此对于复杂的XML文件，我觉得最好还是用验证的解析器来处理。<br></p><img src ="http://www.cppblog.com/mzty/aggbug/30057.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-08-15 10:28 <a href="http://www.cppblog.com/mzty/archive/2007/08/15/30057.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++代码优化（二）</title><link>http://www.cppblog.com/mzty/archive/2007/08/14/30000.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Tue, 14 Aug 2007 09:17:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/08/14/30000.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/30000.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/08/14/30000.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/30000.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/30000.html</trackback:ping><description><![CDATA[&nbsp;谈到优化，很多人都会直接想到汇编。难道优化只能在汇编层次吗？当然不是，C++层次一样可以作代码优化，其中有些常常是意想不到的。在C++层次进行优化，比在汇编层次优化具有更好的移植性，应该是优化中的首选做法。 <br>1.确定浮点型变量和表达式是 float 型 <br>&nbsp;&nbsp;&nbsp; 为了让编译器产生更好的代码(比如说产生3DNow! 或SSE指令的代码)，必须确定浮点型变量和表达式是 float 型的。要特别注意的是，以 "；F"； 或 "；f"； 为后缀（比如：3.14f）的浮点常量才是 float 型，否则默认是 double 型。为了避免 float 型参数自动转化为 double，请在函数声明时使用 float。 <br>2.使用32位的数据类型 <br>　　编译器有很多种，但它们都包含的典型的32位类型是：int，signed，signed int，unsigned，unsigned int，long，signed long，long int，signed long int，unsigned long，unsigned long int。尽量使用32位的数据类型，因为它们比16位的数据甚至8位的数据更有效率。 <br>3.明智使用有符号整型变量 <br>　　在很多情况下，你需要考虑整型变量是有符号还是无符号类型的。比如，保存一个人的体重数据时不可能出现负数，所以不需要使用有符号类型。但是，如果是要保存温度数据，就必须使用到有符号的变量。 <br>　　在许多地方，考虑是否使用有符号的变量是必要的。在一些情况下，有符号的运算比较快；但在一些情况下却相反。 <br>　　比如：整型到浮点转化时，使用大于16位的有符号整型比较快。因为x86构架中提供了从有符号整型转化到浮点型的指令，但没有提供从无符号整型转化到浮点的指令。看看编译器产生的汇编代码： <br>　　不好的代码： <br>编译前 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;编译后 <br>double x；&nbsp;&nbsp;&nbsp;&nbsp;mov [foo + 4], 0 <br>unsigned int i；&nbsp;&nbsp;&nbsp;mov eax, i <br>x = i；&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov [foo], eax <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;flid qword ptr [foo] <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fstp qword ptr [x] <br>　　上面的代码比较慢。不仅因为指令数目比较多，而且由于指令不能配对造成的FLID指令被延迟执行。最好用以下代码代替： <br>&nbsp;&nbsp;&nbsp; 推荐的代码： <br>编译前&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;编译后 <br>double x；&nbsp;&nbsp;&nbsp;&nbsp;fild dword ptr <br>int i；&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fstp qword ptr [x] <br>x = i； <br>　　在整数运算中计算商和余数时，使用无符号类型比较快。以下这段典型的代码是编译器产生的32位整型数除以4的代码： <br>　　不好的代码&nbsp; <br>编译前 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;编译后 <br>int i；&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov eax, i <br>i = i / 4； &nbsp;&nbsp;&nbsp;&nbsp;cdq <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and edx, 3 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add eax, edx <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sar eax, 2 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov i, eax <br>&nbsp;&nbsp;&nbsp; 推荐的代码<br>编译前 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;编译后 <br>unsigned int i； &nbsp;&nbsp;&nbsp;shr i, 2 <br>i = i / 4； <br>　总结：<br>　无符号类型用于：除法和余数,循环计数,数组下标<br>&nbsp; 有符号类型用于：整型到浮点的转化<br>4.while VS. for <br>　　在编程中，我们常常需要用到无限循环，常用的两种方法是while (1) 和 for (；；)。这两种方法效果完全一样，但那一种更好呢？然我们看看它们编译后的代码： <br>编译前 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;编译后 <br>while (1)； &nbsp;&nbsp;&nbsp;&nbsp;mov eax,1 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;test eax,eax <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;je foo+23h <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jmp foo+18h <br>编译前 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;编译后&nbsp; <br>for (；；)； &nbsp;&nbsp;&nbsp;&nbsp;jmp foo+23h <br>　　一目了然，for (；；)指令少，不占用寄存器，而且没有判断跳转，比while (1)好。 <br>5.使用数组型代替指针型 <br>　　使用指针会使编译器很难优化它。因为缺乏有效的指针代码优化的方法，编译器总是假设指针可以访问内存的任意地方，包括分配给其他变量的储存空间。所以为了编译器产生优化得更好的代码，要避免在不必要的地方使用指针。一个典型的例子是访问存放在数组中的数据。C++ 允许使用操作符 [] 或指针来访问数组，使用数组型代码会让优化器减少产生不安全代码的可能性。比如，x[0] 和x[2] 不可能是同一个内存地址，但 *p 和 *q 可能。强烈建议使用数组型，因为这样可能会有意料之外的性能提升。 <br>&nbsp;&nbsp;&nbsp; 不好的代码<br>typedef struct<br>{<br>　　float x,y,z,w；<br>} VERTEX；<br>typedef struct
<p>{<br>　　float m[4][4]；<br>} MATRIX；<br>void XForm(float* res, const float* v, const float* m, int nNumVerts)<br>{<br>　　float dp；<br>　　int i；<br>　　　const VERTEX* vv = (VERTEX *)v；<br>　　　for (i = 0； i &lt;； nNumVerts； i++)<br>　　{<br>　　　　dp = vv-&gt;；x * *m ++；<br>　　　　dp += vv-&gt;；y * *m ++；<br>　　　　dp += vv-&gt;；z * *m ++；<br>　　　　dp += vv-&gt;；w * *m ++；<br>　　　　*res ++ = dp；　　　　　　// 写入转换了的 x<br>　　　　dp = vv-&gt;；x * *m ++；<br>　　　　dp += vv-&gt;；y * *m ++；<br>　　　　dp += vv-&gt;；z * *m ++；<br>　　　　dp += vv-&gt;；w * *m ++；<br>　　　　*res ++ = dp；　　　　　// 写入转换了的 y<br>　　　　dp = vv-&gt;；x * *m ++；<br>　　　　dp += vv-&gt;；y * *m ++；<br>　　　　dp += vv-&gt;；z * *m ++；<br>　　　　dp += vv-&gt;；w * *m ++；<br>　　　　*res ++ = dp；　　　　// 写入转换了的 z<br>　　　　dp = vv-&gt;；x * *m ++；<br>　　　　dp += vv-&gt;；y * *m ++；<br>　　　　dp += vv-&gt;；z * *m ++；<br>　　　　dp += vv-&gt;；w * *m ++；<br>　　　　*res ++ = dp；　　　　// 写入转换了的 w<br>　　　　vv ++；　　　　　　　 // 下一个矢量<br>　　　　m -= 16；<br>　　}<br>}<br>&nbsp;&nbsp;&nbsp; 推荐的代码 <br>typedef struct<br>{<br>　　float x,y,z,w；<br>} VERTEX；<br>typedef struct<br>{<br>　　float m[4][4]；<br>} MATRIX；<br>void XForm (float* res, const float* v, const float* m, int nNumVerts)<br>{<br>　　int i；<br>　　const VERTEX* vv = (VERTEX*)v；<br>　　const MATRIX* mm = (MATRIX*)m；<br>　　VERTEX* rr = (VERTEX*)res；<br>　　for (i = 0； i &lt;； nNumVerts； i++)<br>　　{<br>　　　　rr-&gt;；x = vv-&gt;；x * mm-&gt;；m[0][0] + vv-&gt;；y * mm-&gt;；m[0][1]<br>　　　　　　　　+ vv-&gt;；z * mm-&gt;；m[0][2] + vv-&gt;；w * mm-&gt;；m[0][3]；<br>　　　　rr-&gt;；y = vv-&gt;；x * mm-&gt;；m[1][0] + vv-&gt;；y * mm-&gt;；m[1][1]<br>　　　　　　　　+ vv-&gt;；z * mm-&gt;；m[1][2] + vv-&gt;；w * mm-&gt;；m[1][3]；<br>　　　　rr-&gt;；z = vv-&gt;；x * mm-&gt;；m[2][0] + vv-&gt;；y * mm-&gt;；m[2][1]<br>　　　　　　　　+ vv-&gt;；z * mm-&gt;；m[2][2] + vv-&gt;；w * mm-&gt;；m[2][3]；<br>　　　　rr-&gt;；w = vv-&gt;；x * mm-&gt;；m[3][0] + vv-&gt;；y * mm-&gt;；m[3][1]<br>　　　　　　　　+ vv-&gt;；z * mm-&gt;；m[3][2] + vv-&gt;；w * mm-&gt;；m[3][3]；<br>　　}<br>} <br>　　注意: 源代码的转化是与编译器的代码发生器相结合的。从源代码层次很难控制产生的机器码。依靠编译器和特殊的源代码，有可能指针型代码编译成的机器码比同等条件下的数组型代码运行速度更快。明智的做法是在源代码转化后检查性能是否真正提高了，再选择使用指针型还是数组型。 <br>6.充分分解小的循环 <br>　　要充分利用CPU的指令缓存，就要充分分解小的循环。特别是当循环体本身很小的时候，分解循环可以提高性能。BTW:很多编译器并不能自动分解循环。 <br>不好的代码 推荐的代码 <br>// 3D转化：把矢量 V 和 4x4 矩阵 M 相乘<br>for (i = 0； i &lt;； 4； i ++)<br>{<br>　　r = 0；<br>　　for (j = 0； j &lt;； 4； j ++)<br>　　{<br>　　　　r += M[j]*V[j]；<br>　　}<br>}<br>r[0] = M[0][0]*V[0] + M[1][0]*V[1] + M[2][0]*V[2] + M[3][0]*V[3]；<br>r[1] = M[0][1]*V[0] + M[1][1]*V[1] + M[2][1]*V[2] + M[3][1]*V[3]；<br>r[2] = M[0][2]*V[0] + M[1][2]*V[1] + M[2][2]*V[2] + M[3][2]*V[3]；<br>r[3] = M[0][3]*V[0] + M[1][3]*V[1] + M[2][3]*V[2] + M[3][3]*v[3]； <br>7.避免没有必要的读写依赖 <br>　　当数据保存到内存时存在读写依赖，即数据必须在正确写入后才能再次读取。虽然AMD Athlon等CPU有加速读写依赖延迟的硬件，允许在要保存的数据被写入内存前读取出来，但是，如果避免了读写依赖并把数据保存在内部寄存器中，速度会更快。在一段很长的又互相依赖的代码链中，避免读写依赖显得尤其重要。如果读写依赖发生在操作数组时，许多编译器不能自动优化代码以避免读写依赖。所以推荐程序员手动去消除读写依赖，举例来说，引进一个可以保存在寄存器中的临时变量。这样可以有很大的性能提升。下面一段代码是一个例子： <br>&nbsp;&nbsp;&nbsp; 不好的代码<br>float x[VECLEN], y[VECLEN], z[VECLEN]；<br>...... <br>for (unsigned int k = 1； k &lt;； VECLEN； k ++)<br>{<br>　　x[k] = x[k-1] + y[k]；<br>}<br>for (k = 1； k &lt;； VECLEN； k++)<br>{<br>　　x[k] = z[k] * (y[k] - x[k-1])；<br>}<br>　　 推荐的代码 <br>float x[VECLEN], y[VECLEN], z[VECLEN]；<br>...... <br>float t(x[0])；<br>for (unsigned int k = 1； k &lt;； VECLEN； k ++)<br>{<br>　　t = t + y[k]；<br>　　x[k] = t；<br>}<br>t = x[0]；<br>for (k = 1； k &lt;； VECLEN； k ++)<br>{<br>　　t = z[k] * (y[k] - t)；<br>　　x[k] = t；<br>} <br>8.Switch 的用法 <br>　　Switch 可能转化成多种不同算法的代码。其中最常见的是跳转表和比较链/树。推荐对case的值依照发生的可能性进行排序，把最有可能的放在第一个，当switch用比较链的方式转化时，这样可以提高性能。此外，在case中推荐使用小的连续的整数，因为在这种情况下，所有的编译器都可以把switch 转化成跳转表。 <br>&nbsp;&nbsp;&nbsp; 不好的代码<br>int days_in_month, short_months, normal_months, long_months；<br>...... <br>switch (days_in_month)<br>{<br>　　case 28:<br>　　case 29:<br>　　　　short_months ++；<br>　　　　break；<br>　　case 30:<br>　　　　normal_months ++；<br>　　　　break；<br>　　case 31:<br>　　　　long_months ++；<br>　　　　break；<br>　　default:<br>　　　　cout &lt;；&lt;； "；month has fewer than 28 or more than 31 days"； &lt;；&lt;； endl；<br>　　　　break；<br>}<br>&nbsp;&nbsp;&nbsp; 推荐的代码 <br>int days_in_month, short_months, normal_months, long_months；<br>...... <br>switch (days_in_month)<br>{<br>　　case 31:<br>　　　　long_months ++；<br>　　　　break；<br>　　case 30:<br>　　　　normal_months ++；<br>　　　　break；<br>　　case 28:<br>　　case 29:<br>　　　　short_months ++； <br>　　　　break；<br>　　default:<br>　　　　cout &lt;；&lt;； "；month has fewer than 28 or more than 31 days"； &lt;；&lt;； endl；<br>　　　　break；<br>} <br>9.所有函数都应该有原型定义 <br>　　一般来说，所有函数都应该有原型定义。原型定义可以传达给编译器更多的可能用于优化的信息。 <br>　　尽可能使用常量(const)。C++ 标准规定，如果一个const声明的对象的地址不被获取，允许编译器不对它分配储存空间。这样可以使代码更有效率，而且可以生成更好的代码。 <br>10.提升循环的性能<br>　　要提升循环的性能，减少多余的常量计算非常有用（比如，不随循环变化的计算）。 <br>　　不好的代码(在for()中包含不变的if()) 推荐的代码 <br>for( i ... )<br>{<br>　　if( CONSTANT0 )<br>　　{<br>　　　　DoWork0( i )； // 假设这里不改变CONSTANT0的值<br>　　}<br>　　else<br>　　{<br>　　　　DoWork1( i )； // 假设这里不改变CONSTANT0的值<br>　　}<br>}<br>if( CONSTANT0 )<br>{<br>　　for( i ... )<br>　　{<br>　　　　DoWork0( i )；<br>　　}<br>}<br>else<br>{<br>　　for( i ... )<br>　　{<br>　　　　DoWork1( i )；<br>　　}<br>} <br>　　如果已经知道if()的值，这样可以避免重复计算。虽然不好的代码中的分支可以简单地预测，但是由于推荐的代码在进入循环前分支已经确定，就可以减少对分支预测的依赖。 　　把本地函数声明为静态的(static) <br>　　如果一个函数在实现它的文件外未被使用的话，把它声明为静态的(static)以强制使用内部连接。否则，默认的情况下会把函数定义为外部连接。这样可能会影响某些编译器的优化——比如，自动内联。 <br>11.考虑动态内存分配 <br>　　动态内存分配（C++中的"；new"；）可能总是为长的基本类型（四字对齐）返回一个已经对齐的指针。但是如果不能保证对齐，使用以下代码来实现四字对齐。这段代码假设指针可以映射到 long 型。 <br>　　例子 <br>　　double* p = (double*)new BYTE[sizeof(double) * number_of_doubles+7L]；<br>&nbsp;&nbsp;&nbsp; double* np = (double*)((long(p) + 7L) &amp;； &#8211;8L)； <br>　　现在，你可以使用 np 代替 p 来访问数据。注意：释放储存空间时仍然应该用delete p。 <br>12.使用显式的并行代码 <br>　　尽可能把长的有依赖的代码链分解成几个可以在流水线执行单元中并行执行的没有依赖的代码链。因为浮点操作有很长的潜伏期，所以不管它被映射成 x87 或 3DNow! 指令，这都很重要。很多高级语言，包括C++，并不对产生的浮点表达式重新排序，因为那是一个相当复杂的过程。需要注意的是，重排序的代码和原来的代码在代数上一致并不等价于计算结果一致，因为浮点操作缺乏精确度。在一些情况下，这些优化可能导致意料之外的结果。幸运的是，在大部分情况下，最后结果可能只有最不重要的位（即最低位）是错误的。 <br>　　不好的代码<br>double a[100], sum；<br>int i；<br>sum = 0.0f；<br>for (i=0； i&lt;；100； i++)<br>　　sum += a； <br>&nbsp;&nbsp;&nbsp; 推荐的代码 <br>double a[100], sum1, sum2, sum3, sum4, sum；<br>int i；<br>sum1 = sum2 = sum3 = sum4 = 0.0；<br>for (i = 0； i &lt;； 100； i += 4)<br>{<br>　　sum1 += a；<br>　　sum2 += a[i+1]；<br>　　sum3 += a[i+2]；<br>　　sum4 += a[i+3]；<br>}<br>sum = (sum4+sum3)+(sum1+sum2)； <br>　　要注意的是：使用4 路分解是因为这样使用了4阶段流水线浮点加法，浮点加法的每一个阶段占用一个时钟周期，保证了最大的资源利用率。 <br>13.提出公共子表达式 <br>　　在某些情况下，C++编译器不能从浮点表达式中提出公共的子表达式，因为这意味着相当于对表达式重新排序。需要特别指出的是，编译器在提取公共子表达式前不能按照代数的等价关系重新安排表达式。这时，程序员要手动地提出公共的子表达式（在VC.net里有一项&#8220;全局优化&#8221;选项可以完成此工作，但效果就不得而知了）。 <br>推荐的代码 <br>float a, b, c, d, e, f；<br>...<br>e = b * c / d；<br>f = b / d * a；<br>float a, b, c, d, e, f；<br>...<br>const float t(b / d)；<br>e = c * t；<br>f = a * t； <br>推荐的代码 <br>float a, b, c, e, f；<br>...<br>e = a / c；<br>f = b / c；<br>float a, b, c, e, f；<br>...<br>const float t(1.0f / c)；<br>e = a * t；<br>f = b * t； <br>14.结构体成员的布局 <br>　　很多编译器有&#8220;使结构体字，双字或四字对齐&#8221;的选项。但是，还是需要改善结构体成员的对齐，有些编译器可能分配给结构体成员空间的顺序与他们声明的不同。但是，有些编译器并不提供这些功能，或者效果不好。所以，要在付出最少代价的情况下实现最好的结构体和结构体成员对齐，建议采取这些方法： <br>　　A按类型长度排序 <br>　　把结构体的成员按照它们的类型长度排序，声明成员时把长的类型放在短的前面。 <br>　　把结构体填充成最长类型长度的整倍数 <br>　　把结构体填充成最长类型长度的整倍数。照这样，如果结构体的第一个成员对齐了，所有整个结构体自然也就对齐了。下面的例子演示了如何对结构体成员进行重新排序： <br>　　不好的代码，普通顺序 推荐的代码，新的顺序并手动填充了几个字节<br>struct<br>{<br>　　char a[5]；<br>　　long k；<br>　　double x；<br>} baz；<br>struct<br>{<br>　　double x；<br>　　long k；<br>　　char a[5]；<br>char pad[7]；<br>} baz； </p>
<p>　　这个规则同样适用于类的成员的布局。 <br>　　B按数据类型的长度排序本地变量 <br>　　当编译器分配给本地变量空间时，它们的顺序和它们在源代码中声明的顺序一样，和上一条规则一样，应该把长的变量放在短的变量前面。如果第一个变量对齐了，其它变量就会连续的存放，而且不用填充字节自然就会对齐。有些编译器在分配变量时不会自动改变变量顺序，有些编译器不能产生4字节对齐的栈，所以4字节可能不对齐。下面这个例子演示了本地变量声明的重新排序： <br>　　不好的代码，普通顺序 推荐的代码，改进的顺序 <br>short ga, gu, gi；<br>long foo, bar；<br>double x, y, z[3]；<br>char a, b；<br>float baz；<br>double z[3]；<br>double x, y；<br>long foo, bar；<br>float baz；<br>short ga, gu, gi； <br>14.避免不必要的整数除法 <br>　　整数除法是整数运算中最慢的，所以应该尽可能避免。一种可能减少整数除法的地方是连除，这里除法可以由乘法代替。这个替换的副作用是有可能在算乘积时会溢出，所以只能在一定范围的除法中使用。 <br>　　不好的代码 推荐的代码 <br>int i, j, k, m；<br>m = i / j / k；<br>int i, j, k, m；<br>m = i / (j * k)； <br>15.把频繁使用的指针型参数拷贝到本地变量 <br>　　避免在函数中频繁使用指针型参数指向的值。因为编译器不知道指针之间是否存在冲突，所以指针型参数往往不能被编译器优化。这样是数据不能被存放在寄存器中，而且明显地占用了内存带宽。注意，很多编译器有&#8220;假设不冲突&#8221;优化开关（在VC里必须手动添加编译器命令行/Oa或/Ow），这允许编译器假设两个不同的指针总是有不同的内容，这样就不用把指针型参数保存到本地变量。否则，请在函数一开始把指针指向的数据保存到本地变量。如果需要的话，在函数结束前拷贝回去。 　　<br>&nbsp;&nbsp;&nbsp; 不好的代码 <br>// 假设 q != r<br>void isqrt(unsigned long a, unsigned long* q, unsigned long* r)<br>{<br>　　*q = a；<br>　　if (a &gt;； 0)<br>　　{<br>　　　　while (*q &gt;； (*r = a / *q))<br>　　　　{<br>　　　　　　*q = (*q + *r) &gt;；&gt;； 1；<br>　　　　}<br>　　}<br>　　*r = a - *q * *q；<br>}<br>&nbsp;&nbsp;&nbsp; 推荐的代码<br>// 假设 q != r<br>void isqrt(unsigned long a, unsigned long* q, unsigned long* r)<br>{<br>　　unsigned long qq, rr；<br>　　qq = a；<br>　　if (a &gt;； 0)<br>　　{<br>　　　　while (qq &gt;； (rr = a / qq))<br>　　　　{<br>　　　　　　qq = (qq + rr) &gt;；&gt;； 1；<br>　　　　}<br>　　}<br>　　rr = a - qq * qq；<br>　　*q = qq；<br>　　*r = rr；<br>} <br>16.赋值与初始化<br>先看看以下代码： <br>class CInt<br>{<br>　　int m_i； <br>public:<br>　　CInt(int a = 0):m_i(a) { cout &lt;；&lt;； "；CInt"； &lt;；&lt;； endl； }<br>　　~CInt() { cout &lt;；&lt;； "；~CInt"； &lt;；&lt;； endl； } <br>　　CInt operator + (const CInt&amp;； a) { return CInt(m_i + a.GetInt())； } <br>　　void SetInt(const int i)　　{ m_i = i； }<br>　　int GetInt() const　　　　　　{ return m_i； }<br>}；<br>&nbsp;&nbsp;&nbsp; 不好的代码 <br>void main()<br>{<br>　　CInt a, b, c；<br>　　a.SetInt(1)；<br>　　b.SetInt(2)；<br>　　c = a + b；<br>}<br>&nbsp;&nbsp;&nbsp; 推荐的代码<br>void main()<br>{<br>　　CInt a(1), b(2)；<br>　　CInt c(a + b)；<br>} <br>　　这两段代码所作的事都一样，但那一个更好呢？看看输出结果就会发现，不好的代码输出了四个"；CInt"；和四个"；~CInt"；，而推荐的代码只输出三个。也就是说，第二个例子比第一个例子少生成一次临时对象。Why? 请注意，第一个中的c用的是先声明再赋值的方法，第二个用的是初始化的方法，它们有本质的区别。第一个例子的"；c = a + b"；先生成一个临时对象用来保存a + b的值，再把该临时对象用位拷贝的方法给c赋值，然后临时对象被销毁。这个临时对象就是那个多出来的对象。第二个例子直接用拷贝构造函数的方法对c初始化，不产生临时对象。所以，尽量在需要使用一个对象时才声明，并用初始化的方法赋初值。 <br>17.尽量使用成员初始化列表 <br>　　在初始化类的成员时，尽量使用成员初始化列表而不是传统的赋值方式。 <br>　　不好的代码 <br>class CMyClass<br>{<br>　　string strName； <br>public:<br>　　CMyClass(const string&amp;； str)；<br>}； <br>CMyClass::CMyClass(const string&amp;； str)<br>{<br>　　strName = str；<br>}<br>&nbsp;&nbsp;&nbsp; 推荐的代码<br>class CMyClass<br>{<br>　　string strName；<br>　　int i；<br>public:<br>　　CMyClass(const string&amp;； str)；<br>}； <br>CMyClass::CMyClass(const string&amp;；str)<br>&nbsp;&nbsp; :strName(str)<br>{</p>
<p>} <br>　　不好的例子用的是赋值的方式。这样，strName会先被建立（调用了string的默认构造函数），再由参数str赋值。而推荐的例子用的是成员初始化列表，strName直接构造为str，少调用一次默认构造函数，还少了一些安全隐患。</p><img src ="http://www.cppblog.com/mzty/aggbug/30000.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-08-14 17:17 <a href="http://www.cppblog.com/mzty/archive/2007/08/14/30000.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>STL函数对象及函数对象适配器</title><link>http://www.cppblog.com/mzty/archive/2007/08/14/29962.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Tue, 14 Aug 2007 03:37:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/08/14/29962.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/29962.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/08/14/29962.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/29962.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/29962.html</trackback:ping><description><![CDATA[<p>STL函数对象及函数对象适配器</p>
<p><br>一 <span style="BACKGROUND-COLOR: #ff00ff">函数对象Functor</span></p>
<p>&nbsp;&nbsp;&nbsp; STL中提供了一元和二元函数的两种Functor,通过unary_function和binary_function提供了这两种不同参数数量的Functor的基本结构,在这两个类型中,分别内嵌定义一元和二元函数操作在模版推演的时候需要用到的typedef.<br>&nbsp;</p>
<p>//一元函数的定义为<br>template&lt;class _A, class _R&gt;<br>struct unary_function {<br>&nbsp;typedef _A argument_type;<br>&nbsp;typedef _R result_type;<br>};</p>
<p><br>//二元函数的定义为<br>template&lt;class _A1, class _A2, class _R&gt;<br>&nbsp;struct binary_function {<br>&nbsp;typedef _A1 first_argument_type;<br>&nbsp;typedef _A2 second_argument_type;<br>&nbsp;typedef _R result_type;<br>};</p>
<p>其他的一元和二元Functor可以从这两个基本结构继承,同时也就可以推演出函数的参数和返回值的类型,STL在上述这两个结构的基础上,实现了很多一元和二元的Functor.</p>
<p>//一元<br>negate</p>
<p>//二元<br>plus<br>minus<br>multiplies<br>divides<br>modulus<br>equal_to<br>not_equal_to<br>greater<br>greater_equal <br>less<br>less_equal<br>logical_and<br>logical_or<br>logical_not</p>
<p>上面的这些Functor都是基于模版实现的,可以象下面那样使用的方式:</p>
<p>plus&lt;int&gt; int_plus;<br>cout &lt;&lt; int_plus(111,222) &lt;&lt; endl;</p>
<p><br>二 <span style="BACKGROUND-COLOR: #ff00ff">函数对象适配器</span></p>
<p>函数对象适配器的作用就是使函数转化为函数对象，或是将多参数的函数对象转化为少参数的函数对象。</p>
<p><br>1）bind</p>
<p>bind1st&nbsp; //通过绑定第一个参数，使二元的函数对象转化为一元的函数对象<br>bind2nd&nbsp; //通过绑定第二个参数，使二元的函数对象转化为一元的函数对象<br>not1&nbsp;&nbsp;&nbsp;&nbsp; //对一元的函数对象取反<br>not2&nbsp;&nbsp;&nbsp;&nbsp; //对二元的函数对象取反</p>
<p>使用的方式:<br>bind1st( less&lt;int&gt;(), 10)(20);<br>not2( less&lt;int() )(10,20);</p>
<p>这些Functor看起来好像好像用处不大,但是在和STL中的容器和算法结合在一起使用的时候,就会使得程序显得很简洁.</p>
<p>int i;&nbsp;&nbsp;&nbsp; <br>vector&lt;int&gt; lv;<br>for(i = 0; i &lt; 100; i++) <br>{<br>&nbsp;&nbsp;&nbsp; lv.push_back(i);<br>}<br>//对vector中小于20的数进行记数<br>cout &lt;&lt; count_if(lv.begin(), lv.end(), bind2nd(less&lt;int&gt;(), 20)) &lt;&lt; endl;</p>
<p>//由大到小排序<br>sort(lv.begin(), lv.end(), not2(less&lt;int&gt;()) ) ;<br>for (i = 0; i &lt; 100; i++) <br>{<br>&nbsp;&nbsp;&nbsp; cout &lt;&lt; lv.at(i) &lt;&lt; endl;<br>}</p>
<p><br>2）ptr_fun</p>
<p>ptr_fun是指将现有的函数转换为Functor的功能.在STL中提供了这个功能的Functor,就是pointer_to_unary_function和pointer_to_binary_function这两个类,这两个类对应一元</p>
<p>和二元两种函数,也就是说,对于调用参数为3个或者多于3个的函数,STL提供的Functor类,无法配接.</p>
<p>基本使用方法:</p>
<p>int u_func(int a)<br>{<br>&nbsp;&nbsp;&nbsp; int ret = a;<br>&nbsp;&nbsp;&nbsp; return ret;<br>}&nbsp;&nbsp;&nbsp; </p>
<p>int b_func(int a,int b)<br>{<br>&nbsp;&nbsp;&nbsp; return a+b;<br>}</p>
<p>void call()<br>{<br>&nbsp;pointer_to_unary_function&lt;int,int&gt; uf(u_func);<br>&nbsp;&nbsp;&nbsp; cout &lt;&lt; uf(100) &lt;&lt; endl;<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; pointer_to_binary_function&lt;int,int,int&gt; bf(b_func);<br>&nbsp;&nbsp;&nbsp; cout &lt;&lt; bf(111,222) &lt;&lt; endl;</p>
<p>&nbsp;//或者<br>&nbsp;cout &lt;&lt; ptr_fun(u_func)(100) &lt;&lt; endl;<br>&nbsp;&nbsp;&nbsp; cout &lt;&lt; ptr_fun(b_func)(111,222) &lt;&lt; endl;</p>
<p>}<br>可以看到,上面的方法改进了原先C和C++中通过函数指针来间接调用函数的方法,将函数指针封装到了类中.</p>
<p><br>问题:</p>
<p>第一部分中的Functor中是自己定义操作符(),但是在ptr_fun中,是将已经有的function转为Functor调用就会存在一个调用方式的问题.</p>
<p>c++中的函数,按调用方式可以分为__cdecl, __stdcall,__fastcall 三种,ptr_fun如何正确的识别给定的function的调用方式就会有问题.</p>
<p>其中:<br>vc6中的STL的ptr_fun代码中,统一将function认为是__cdecl调用方式. 而Dev-cpp中使用的SGI的代码中没有明确指明函数的调用方式,所以将使用编译器的确省设置.<br>但是如果将上面的b_func函数改为<br>int __stdcall b_func(int a,int b)<br>{<br>&nbsp;&nbsp;&nbsp; return a+b;<br>}<br>上面的使用代码在DEV-CPP中无法编译通过.</p>
<p>3）mem_fun</p>
<p>mem_fun是将某个类中的成员函数转变为Functor的功能. </p>
<p>一般的使用方法<br>struct mem_fun_struct<br>{<br>&nbsp;&nbsp;&nbsp; int n_mem_fun() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "mem_fun_struct::n_mem_fun()" &lt;&lt; endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; int u_mem_fun(int a) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "mem_fun_struct::u_mem_fun(int) " &lt;&lt; a &lt;&lt; endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return a;<br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; int b_mem_fun(int a,int b) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "mem_fun_struct::b_mem_fun(int,int)" &lt;&lt; a &lt;&lt; " " &lt;&lt; b &lt;&lt; endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return a+b;<br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br>};</p>
<p>void call()<br>{<br>&nbsp;mem_fun_struct ls;<br>&nbsp;&nbsp;&nbsp; mem_fun(&amp;mem_fun_struct::n_mem_fun)(&amp;ls);<br>&nbsp;&nbsp;&nbsp; mem_fun(&amp;mem_fun_struct::u_mem_fun)(&amp;ls, 10);<br>&nbsp;&nbsp;&nbsp; //mem_fun(&amp;mem_fun_struct::u_mem_fun)(&amp;ls, 10, 20);<br>}</p>
<p>上面的代码在dev-cpp 4.9.9中编译通过,SGI STL中没有提供二元成员函数的mem_fun，vc6中提供了mem_fun(无参数成员函数)和mem_fun1(一元参数成员函数), 而在vs2003中改变了用法.但是我看MSDN好像也只支持到一个参数.</p>
<p>三 <span style="BACKGROUND-COLOR: #ff00ff">总结</span></p>
<p>STL中提供了基本的一元和二元参数的Functor, 同时提供了相应的适配器可以对Functor进行修饰,Functor可以很好的和 STL容器,STL算法结合使用.</p>
<p>但是仍有问题：<br>1）上面说到的调用方式<br>2） 多参数函数对象适配</p>
<p>对于我们比较复杂的stl不能满足要求的问题，我们可以是用boost或loki来解决。</p>
<p><br>四 <span style="BACKGROUND-COLOR: #ff00ff">参考</span></p>
<p>本文基本是对hdqqq的文章转载，稍加整理！原文地址：<a href="http://www.cppblog.com/hdqqq/archive/2006/09/13/12424.aspx">http://www.cppblog.com/hdqqq/archive/2006/09/13/12424.aspx</a></p>
<p>同时参考msdn：<a href="http://msdn2.microsoft.com/en-us/library/4y7z5x4b(VS.80).aspx">http://msdn2.microsoft.com/en-us/library/4y7z5x4b(VS.80).aspx</a><br>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p><img src ="http://www.cppblog.com/mzty/aggbug/29962.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-08-14 11:37 <a href="http://www.cppblog.com/mzty/archive/2007/08/14/29962.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++随笔分类列表（高级）</title><link>http://www.cppblog.com/mzty/archive/2007/08/13/29922.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Mon, 13 Aug 2007 10:27:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/08/13/29922.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/29922.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/08/13/29922.html#Feedback</comments><slash:comments>14</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/29922.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/29922.html</trackback:ping><description><![CDATA[<p>C++随笔分类列表（高级）:</p>
<p>C++精华：<br>61条面向对象的设计原则 <a href="http://www.cppblog.com/mzty/archive/2005/12/29/2247.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2005/12/29/2247.html</font></a><br>c＋＋资源 <a href="http://www.cppblog.com/mzty/archive/2005/11/16/1148.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2005/11/16/1148.html</font></a><br>C++ Style and Technique FAQ&nbsp; <a href="http://www.cppblog.com/mzty/archive/2005/11/30/1437.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2005/11/30/1437.html</font></a><br>微软C++标准（事件实例） <a href="http://www.cppblog.com/mzty/archive/2006/11/25/15657.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2006/11/25/15657.html</font></a><br>c++代码优化总结&nbsp; <a href="http://www.cppblog.com/mzty/archive/2005/12/29/2249.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2005/12/29/2249.html</font></a><br><a id=viewpost1_TitleUrl href="http://www.cppblog.com/mzty/archive/2007/08/14/30000.html"><font color=#223355>C++代码优化（二）</font></a> <a href="http://www.cppblog.com/mzty/archive/2007/08/14/30000.html">http://www.cppblog.com/mzty/archive/2007/08/14/30000.html</a><br><a id=_2b55cadf2054_HomePageDays_DaysList_ctl03_DayItem_DayList_ctl01_TitleUrl href="http://www.cppblog.com/mzty/archive/2007/04/20/22349.html"><font color=#223355>C++调用约定和名字约定</font></a>&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/04/20/22349.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2007/04/20/22349.html</font></a><br><a id=viewpost1_TitleUrl href="http://www.cppblog.com/mzty/archive/2007/07/19/28359.html"><font color=#223355>C++高效编程忠告</font></a> <a href="http://www.cppblog.com/mzty/archive/2007/07/19/28359.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2007/07/19/28359.html</font></a><br><a id=_2b55cadf2054_HomePageDays_DaysList_ctl00_DayItem_DayList_ctl01_TitleUrl href="http://www.cppblog.com/mzty/archive/2007/05/24/24774.html"><font color=#223355>策略模式（policy）</font></a>&nbsp;<a href="http://www.cppblog.com/mzty/archive/2007/05/24/24774.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2007/05/24/24774.html</font></a><br>C++接口与实现分离的2种方法&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/08/06/29441.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2007/08/06/29441.html</font></a><br><a id=viewpost1_TitleUrl href="http://www.cppblog.com/mzty/archive/2007/12/03/37679.html"><font color=#223355>堆栈，堆栈，堆和栈的区别（再转）</font></a> <a href="http://www.cppblog.com/mzty/archive/2007/12/03/37679.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2007/12/03/37679.html</font></a><br><a id=viewpost1_TitleUrl href="http://www.cppblog.com/mzty/archive/2008/02/18/42877.html"><font color=#223355>C++ 虚函数表解析（转）</font></a> <br><br><br>C++字符:<br>C++字符串完全指引之一 —— Win32 字符编码 <a href="http://www.cppblog.com/mzty/archive/2005/12/06/1565.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2005/12/06/1565.html</font></a><br>C++字符串完全指引之二 —— 字符串封装类&nbsp; <a href="http://www.cppblog.com/mzty/archive/2005/12/06/1564.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2005/12/06/1564.html</font></a><br>Visual C++.NET中 字符串转换方法 <a href="http://www.cppblog.com/mzty/archive/2005/12/23/2000.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2005/12/23/2000.html</font></a><br>com中的字符串&nbsp; <a href="http://www.cppblog.com/mzty/archive/2005/12/23/2001.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2005/12/23/2001.html</font></a><br>编码,charset,乱码,unicode,utf-8与net简单释义(转)&nbsp; <a href="http://www.cppblog.com/mzty/archive/2006/07/14/9832.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2006/07/14/9832.html</font></a><br>C++中各种string的相互转化&nbsp;&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/08/07/29307.html"><font color=#1d58d1>http://www.cppblog.com/mzty/archive/2007/08/07/29307.html</font></a><br><br><br>STL:<br>STL算法学习&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/03/14/19819.html">http://www.cppblog.com/mzty/archive/2007/03/14/19819.html</a><br>stl容器学习总结&nbsp;&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/03/15/19875.html">http://www.cppblog.com/mzty/archive/2007/03/15/19875.html</a><br>STL函数对象及函数对象适配器 <a href="http://www.cppblog.com/mzty/archive/2007/08/14/29962.html">http://www.cppblog.com/mzty/archive/2007/08/14/29962.html</a><br></p>
<p><br>Boost：<br><a id=viewpost1_TitleUrl href="http://www.cppblog.com/mzty/archive/2007/08/15/30095.html"><font color=#223355>引领Boost（一）（开篇）</font></a> <a href="http://www.cppblog.com/mzty/archive/2007/08/15/30095.html">http://www.cppblog.com/mzty/archive/2007/08/15/30095.html</a><br><a id=viewpost1_TitleUrl href="http://www.cppblog.com/mzty/archive/2007/08/16/30156.html"><font color=#223355>引领Boost（二）（Boost::Any）</font></a>&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/08/16/30156.html">http://www.cppblog.com/mzty/archive/2007/08/16/30156.html</a><br><a id=viewpost1_TitleUrl href="http://www.cppblog.com/mzty/archive/2007/08/21/30509.html"><font color=#223355>引领Boost（三）（Boost::tuple）</font></a> <a href="http://www.cppblog.com/mzty/archive/2007/08/21/30509.html">http://www.cppblog.com/mzty/archive/2007/08/21/30509.html</a><br><a id=viewpost1_TitleUrl href="http://www.cppblog.com/mzty/archive/2007/08/22/30611.html"><font color=#223355>引领Boost（四）（Boost::smart_ptr）</font></a> <a href="http://www.cppblog.com/mzty/archive/2007/08/22/30611.html">http://www.cppblog.com/mzty/archive/2007/08/22/30611.html</a><br><a id=viewpost1_TitleUrl href="http://www.cppblog.com/mzty/archive/2007/08/24/30775.html"><font color=#223355>引领Boost（五）（Boost::array）</font></a>&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/08/24/30775.html">http://www.cppblog.com/mzty/archive/2007/08/24/30775.html</a><br><a id=viewpost1_TitleUrl href="http://www.cppblog.com/mzty/archive/2007/09/05/31622.html"><font color=#223355>引领boost（六）（boost::bind）</font></a>&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/09/05/31622.html">http://www.cppblog.com/mzty/archive/2007/09/05/31622.html</a><br><br>C++单元测试：<br>用cppunit进行单元测试&nbsp; <a href="http://www.cppblog.com/mzty/archive/2005/12/28/2201.html">http://www.cppblog.com/mzty/archive/2005/12/28/2201.html</a><br>cppunit 使用： <a href="http://www.cppblog.com/mzty/archive/2007/06/25/26948.html">http://www.cppblog.com/mzty/archive/2007/06/25/26948.html</a></p>
<p>C++内存泄露检测：<br>C++内存泄露的检测（一） <a href="http://www.cppblog.com/mzty/archive/2007/07/19/28361.html">http://www.cppblog.com/mzty/archive/2007/07/19/28361.html</a><br>C++内存泄露的检测（二） <a href="http://www.cppblog.com/mzty/archive/2007/07/23/28638.html">http://www.cppblog.com/mzty/archive/2007/07/23/28638.html</a><br>C++内存泄露的检测（三） <a href="http://www.cppblog.com/mzty/archive/2007/07/23/28647.html">http://www.cppblog.com/mzty/archive/2007/07/23/28647.html</a><br>C++内存泄露的检测（四） <a href="http://www.cppblog.com/mzty/archive/2007/07/24/28673.html">http://www.cppblog.com/mzty/archive/2007/07/24/28673.html</a></p>
<p><br>多线程编程：<br>c++的多线程编程（资料收集）<a href="http://www.cppblog.com/mzty/archive/2007/03/16/19972.html">http://www.cppblog.com/mzty/archive/2007/03/16/19972.html</a><br>C++多线程（一）&nbsp;&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/07/24/28713.html">http://www.cppblog.com/mzty/archive/2007/07/24/28713.html</a><br>C++多线程（二）&nbsp;&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/07/25/28756.html">http://www.cppblog.com/mzty/archive/2007/07/25/28756.html</a><br>C++多线程（三）&nbsp;&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/07/25/28775.html">http://www.cppblog.com/mzty/archive/2007/07/25/28775.html</a><br>C++多线程（四）&nbsp;&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/07/26/28833.html">http://www.cppblog.com/mzty/archive/2007/07/26/28833.html</a><br>C++多线程（五）&nbsp;&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/07/28/28836.html">http://www.cppblog.com/mzty/archive/2007/07/28/28836.html</a><br>C++多线程（六）&nbsp;&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/07/29/28837.html">http://www.cppblog.com/mzty/archive/2007/07/29/28837.html</a><br>C++多线程（七）&nbsp;&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/07/30/28838.html">http://www.cppblog.com/mzty/archive/2007/07/30/28838.html</a><br>C++多线程（八）&nbsp;&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/07/31/28839.html">http://www.cppblog.com/mzty/archive/2007/07/31/28839.html</a><br>C++多线程（九）&nbsp;&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/08/01/28892.html">http://www.cppblog.com/mzty/archive/2007/08/01/28892.html</a><br>C++多线程（十）&nbsp;&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/08/02/29155.html">http://www.cppblog.com/mzty/archive/2007/08/02/29155.html</a><br><a id=_336b5cf1c939_HomePageDays_DaysList_ctl05_DayItem_DayList_ctl00_TitleUrl href="http://www.cppblog.com/mzty/archive/2008/07/29/57470.html"><font color=#0066aa>《windows via C++》之windows线程同步</font></a></p>
<p><br>范型编程:<br>泛型编程 ，知多少？&nbsp; <a href="http://www.cppblog.com/mzty/archive/2005/11/18/1188.html">http://www.cppblog.com/mzty/archive/2005/11/18/1188.html</a><br>模版套模版 <a href="http://www.cppblog.com/mzty/archive/2007/02/26/18996.html">http://www.cppblog.com/mzty/archive/2007/02/26/18996.html</a><br>模版元编程（Template Meta Programming ）<a href="http://www.cppblog.com/mzty/archive/2007/03/05/19219.html">http://www.cppblog.com/mzty/archive/2007/03/05/19219.html</a><br>C++模版全掌握（实例）<a href="http://www.cppblog.com/mzty/archive/2007/05/24/24761.html">http://www.cppblog.com/mzty/archive/2007/05/24/24761.html</a><br>C++模版：编译期检测可转换和可继承&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/05/24/24772.html">http://www.cppblog.com/mzty/archive/2007/05/24/24772.html</a><br>C++模版使用技巧--Int2Type&nbsp; <a href="http://www.cppblog.com/mzty/archive/2007/05/24/24775.html">http://www.cppblog.com/mzty/archive/2007/05/24/24775.html</a></p>
<p>&nbsp;</p><img src ="http://www.cppblog.com/mzty/aggbug/29922.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-08-13 18:27 <a href="http://www.cppblog.com/mzty/archive/2007/08/13/29922.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++中各种string的相互转化</title><link>http://www.cppblog.com/mzty/archive/2007/08/07/29307.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Tue, 07 Aug 2007 13:28:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/08/07/29307.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/29307.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/08/07/29307.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/29307.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/29307.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一 C++ 中 string与wstring互转方法一：string&nbsp;WideToMutilByte(const&nbsp;wstring&amp;&nbsp;_src){int&nbsp;nBufSize&nbsp;=&nbsp;WideCharToMultiByte(GetACP(),&nbsp;0,&nbsp;_src.c_str(),-1,&nbsp;NULL,&nbsp;0...&nbsp;&nbsp;<a href='http://www.cppblog.com/mzty/archive/2007/08/07/29307.html'>阅读全文</a><img src ="http://www.cppblog.com/mzty/aggbug/29307.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-08-07 21:28 <a href="http://www.cppblog.com/mzty/archive/2007/08/07/29307.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++接口与实现分离的2种方法</title><link>http://www.cppblog.com/mzty/archive/2007/08/06/29441.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Mon, 06 Aug 2007 15:17:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/08/06/29441.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/29441.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/08/06/29441.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/29441.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/29441.html</trackback:ping><description><![CDATA[<br>方法一：使用另一个实现类分装类的私有成员和函数，这种方法称为Pimpl方法。<br><br>test.h<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: #000000">#pragma&nbsp;once<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">shared_ptr.hpp</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><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;CTest<br><img id=Codehighlighter1_51_175_Open_Image onclick="this.style.display='none'; Codehighlighter1_51_175_Open_Text.style.display='none'; Codehighlighter1_51_175_Closed_Image.style.display='inline'; Codehighlighter1_51_175_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_51_175_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_51_175_Closed_Text.style.display='none'; Codehighlighter1_51_175_Open_Image.style.display='inline'; Codehighlighter1_51_175_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_51_175_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_51_175_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;CTest(</span><span style="COLOR: #0000ff">void</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">CTest(</span><span style="COLOR: #0000ff">void</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">void</span><span style="COLOR: #000000">&nbsp;DoSomething();<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></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;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CTestImp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;boost::shared_ptr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">CTestImp</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;pimpl_;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;</span></div>
<br>test.cpp<br>
<p>&#160;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Test.h</span><span style="COLOR: #000000">"</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">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><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;CTest::CTestImp<br><img id=Codehighlighter1_61_188_Open_Image onclick="this.style.display='none'; Codehighlighter1_61_188_Open_Text.style.display='none'; Codehighlighter1_61_188_Closed_Image.style.display='inline'; Codehighlighter1_61_188_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_61_188_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_61_188_Closed_Text.style.display='none'; Codehighlighter1_61_188_Open_Image.style.display='inline'; Codehighlighter1_61_188_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_61_188_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_61_188_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 id=Codehighlighter1_99_100_Open_Image onclick="this.style.display='none'; Codehighlighter1_99_100_Open_Text.style.display='none'; Codehighlighter1_99_100_Closed_Image.style.display='inline'; Codehighlighter1_99_100_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_99_100_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_99_100_Closed_Text.style.display='none'; Codehighlighter1_99_100_Open_Image.style.display='inline'; Codehighlighter1_99_100_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CTestImp(CTestImp&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">)</span><span id=Codehighlighter1_99_100_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_99_100_Open_Text><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_141_142_Open_Image onclick="this.style.display='none'; Codehighlighter1_141_142_Open_Text.style.display='none'; Codehighlighter1_141_142_Closed_Image.style.display='inline'; Codehighlighter1_141_142_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_141_142_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_141_142_Closed_Text.style.display='none'; Codehighlighter1_141_142_Open_Image.style.display='inline'; Codehighlighter1_141_142_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CTestImp&nbsp;</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">(CTestImp&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">)</span><span id=Codehighlighter1_141_142_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_141_142_Open_Text><span style="COLOR: #000000">{}</span></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></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img id=Codehighlighter1_164_165_Open_Image onclick="this.style.display='none'; Codehighlighter1_164_165_Open_Text.style.display='none'; Codehighlighter1_164_165_Closed_Image.style.display='inline'; Codehighlighter1_164_165_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_164_165_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_164_165_Closed_Text.style.display='none'; Codehighlighter1_164_165_Open_Image.style.display='inline'; Codehighlighter1_164_165_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CTestImp()</span><span id=Codehighlighter1_164_165_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_164_165_Open_Text><span style="COLOR: #000000">{}</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">void</span><span style="COLOR: #000000">&nbsp;DoSomething();<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;CTest::CTestImp::DoSomething()<br><img id=Codehighlighter1_228_298_Open_Image onclick="this.style.display='none'; Codehighlighter1_228_298_Open_Text.style.display='none'; Codehighlighter1_228_298_Closed_Image.style.display='inline'; Codehighlighter1_228_298_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_228_298_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_228_298_Closed_Text.style.display='none'; Codehighlighter1_228_298_Open_Image.style.display='inline'; Codehighlighter1_228_298_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_228_298_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_228_298_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: #008000">//</span><span style="COLOR: #008000">&nbsp;do&nbsp;something.</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;std::cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Imp&nbsp;class&nbsp;do&nbsp;something.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">std::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>CTest::CTest(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_320_387_Open_Image onclick="this.style.display='none'; Codehighlighter1_320_387_Open_Text.style.display='none'; Codehighlighter1_320_387_Closed_Image.style.display='inline'; Codehighlighter1_320_387_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_320_387_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_320_387_Closed_Text.style.display='none'; Codehighlighter1_320_387_Open_Image.style.display='inline'; Codehighlighter1_320_387_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_320_387_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_320_387_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;boost::shared_ptr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">CTestImp</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;pImp(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;CTestImp);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pimpl_&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;pImp;<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>CTest::</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">CTest(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_410_412_Open_Image onclick="this.style.display='none'; Codehighlighter1_410_412_Open_Text.style.display='none'; Codehighlighter1_410_412_Closed_Image.style.display='inline'; Codehighlighter1_410_412_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_410_412_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_410_412_Closed_Text.style.display='none'; Codehighlighter1_410_412_Open_Image.style.display='inline'; Codehighlighter1_410_412_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_410_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_410_412_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></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;CTest::DoSomething()<br><img id=Codehighlighter1_441_467_Open_Image onclick="this.style.display='none'; Codehighlighter1_441_467_Open_Text.style.display='none'; Codehighlighter1_441_467_Closed_Image.style.display='inline'; Codehighlighter1_441_467_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_441_467_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_441_467_Closed_Text.style.display='none'; Codehighlighter1_441_467_Open_Image.style.display='inline'; Codehighlighter1_441_467_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_441_467_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_441_467_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pimpl_</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">DoSomething();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p><br>方法二：使用抽象类来实现接口与实现的分离。<br><br>x.h&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: #000000">#pragma&nbsp;once<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">stdio.h</span><span style="COLOR: #000000">&gt;</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">"</span><span style="COLOR: #000000">shared_ptr.hpp</span><span style="COLOR: #000000">"</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;boost;<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;X<br><img id=Codehighlighter1_90_193_Open_Image onclick="this.style.display='none'; Codehighlighter1_90_193_Open_Text.style.display='none'; Codehighlighter1_90_193_Closed_Image.style.display='inline'; Codehighlighter1_90_193_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_90_193_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_90_193_Closed_Text.style.display='none'; Codehighlighter1_90_193_Open_Image.style.display='inline'; Codehighlighter1_90_193_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_90_193_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_90_193_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;f()&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: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;g()&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><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">:<br><img id=Codehighlighter1_173_191_Open_Image onclick="this.style.display='none'; Codehighlighter1_173_191_Open_Text.style.display='none'; Codehighlighter1_173_191_Closed_Image.style.display='inline'; Codehighlighter1_173_191_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_173_191_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_173_191_Closed_Text.style.display='none'; Codehighlighter1_173_191_Open_Image.style.display='inline'; Codehighlighter1_173_191_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">X()&nbsp;</span><span id=Codehighlighter1_173_191_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_173_191_Open_Text><span style="COLOR: #000000">{&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">~X\n</span><span style="COLOR: #000000">"</span><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>shared_ptr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">X</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;createX();</span></div>
<p>&nbsp;<br>x.cpp&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: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">X.h</span><span style="COLOR: #000000">"</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">stdio.h</span><span style="COLOR: #000000">&gt;</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;X_impl:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;X<br><img id=Codehighlighter1_58_365_Open_Image onclick="this.style.display='none'; Codehighlighter1_58_365_Open_Text.style.display='none'; Codehighlighter1_58_365_Closed_Image.style.display='inline'; Codehighlighter1_58_365_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_58_365_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_58_365_Closed_Text.style.display='none'; Codehighlighter1_58_365_Open_Image.style.display='inline'; Codehighlighter1_58_365_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_58_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_58_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">private</span><span style="COLOR: #000000">:<br><img id=Codehighlighter1_78_79_Open_Image onclick="this.style.display='none'; Codehighlighter1_78_79_Open_Text.style.display='none'; Codehighlighter1_78_79_Closed_Image.style.display='inline'; Codehighlighter1_78_79_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_78_79_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_78_79_Closed_Text.style.display='none'; Codehighlighter1_78_79_Open_Image.style.display='inline'; Codehighlighter1_78_79_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;X_impl()</span><span id=Codehighlighter1_78_79_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_78_79_Open_Text><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;X_impl(X_impl&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</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;X_impl&nbsp;</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">(X_impl&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</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></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img id=Codehighlighter1_170_192_Open_Image onclick="this.style.display='none'; Codehighlighter1_170_192_Open_Text.style.display='none'; Codehighlighter1_170_192_Closed_Image.style.display='inline'; Codehighlighter1_170_192_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_170_192_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_170_192_Closed_Text.style.display='none'; Codehighlighter1_170_192_Open_Image.style.display='inline'; Codehighlighter1_170_192_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">X_impl()</span><span id=Codehighlighter1_170_192_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_170_192_Open_Text><span style="COLOR: #000000">{printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">~X_impl\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);}</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">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;f()<br><img id=Codehighlighter1_220_257_Open_Image onclick="this.style.display='none'; Codehighlighter1_220_257_Open_Text.style.display='none'; Codehighlighter1_220_257_Closed_Image.style.display='inline'; Codehighlighter1_220_257_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_220_257_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_220_257_Closed_Text.style.display='none'; Codehighlighter1_220_257_Open_Image.style.display='inline'; Codehighlighter1_220_257_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_220_257_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_220_257_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;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">X_impl.f()\n</span><span style="COLOR: #000000">"</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">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;g()<br><img id=Codehighlighter1_284_321_Open_Image onclick="this.style.display='none'; Codehighlighter1_284_321_Open_Text.style.display='none'; Codehighlighter1_284_321_Closed_Image.style.display='inline'; Codehighlighter1_284_321_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_284_321_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_284_321_Closed_Text.style.display='none'; Codehighlighter1_284_321_Open_Image.style.display='inline'; Codehighlighter1_284_321_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_284_321_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_284_321_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;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">X_impl.g()\n</span><span style="COLOR: #000000">"</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></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;friend&nbsp;shared_ptr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">X</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;createX();<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>shared_ptr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">X</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;createX()<br><img id=Codehighlighter1_393_444_Open_Image onclick="this.style.display='none'; Codehighlighter1_393_444_Open_Text.style.display='none'; Codehighlighter1_393_444_Closed_Image.style.display='inline'; Codehighlighter1_393_444_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_393_444_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_393_444_Closed_Text.style.display='none'; Codehighlighter1_393_444_Open_Image.style.display='inline'; Codehighlighter1_393_444_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_393_444_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_393_444_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;shared_ptr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">X</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;px(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;X_impl);<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;px;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br><br>总结：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接口与实现的分离，有助于我们对代码实现的保护，特别是如果我们开发lib共别人使用使，更要注意。在实现分离的过程中，最好采用上面的第一种方法的智能指针boost::shared_ptr的实现，简单安全。<img src ="http://www.cppblog.com/mzty/aggbug/29441.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-08-06 23:17 <a href="http://www.cppblog.com/mzty/archive/2007/08/06/29441.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++多线程（十）</title><link>http://www.cppblog.com/mzty/archive/2007/08/02/29155.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Thu, 02 Aug 2007 01:59:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/08/02/29155.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/29155.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/08/02/29155.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/29155.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/29155.html</trackback:ping><description><![CDATA[<p><br>多线程使用总结<br></p>
<p>基础：</p>
<p>1）最好使用C++ runtime的函数创建线程，即调用_beginthreadex创建线程。CreateThread（）函数并不会执行C运行时数据块的变量的每线程初始化，因此在任何使用C运行时库的应用中，不能使用CrateThread()函数。</p>
<p>2）最好不要显示的调用ExitThread()或TerminateThread（），因为调用这些不进行清理工作。</p>
<p>3）SuspendThread（）挂起线程时，要考虑该线程是否拥有Mutex或Semaphore，如果拥有的话可能会导致死锁。</p>
<p>4）信号量Semaphore，是一个可以限制对指定的临界段进行访问的线程的数目的数据结构。</p>
<p>5）互斥量Mutex和关键代码段CriticalSection，他们的作用是相同的，都是用来保证某时刻只有一个线程能够访问全局或静态的资源。区别是：Mutex是内核对象，可以设置等待超时时间，可以在不同的进程的线程中使用，但是所消耗的时间也比较多。CriticalSection与Mutex相反。</p>
<p>6）互锁函数，可以用来实现原子操作。对于一些简单的问题，比如说int变量的自加，交换。。。</p>
<p>7)线程局部存储（TLS），可以为全局或静态变量对不同的线程有不同的拷贝。<br></p>
<p>高级：</p>
<p>8）线程池，可以实现在程序中根据需要动态的创建线程，比如在server端，根据访问的用户的多少来创建线程的多少。在windows2000以后增加了创建线程池的API，比如 QueueUserWorkItem（）。</p>
<p>9）线程的优先级，用来保证重要的事情先被完成。不能使用线程的优先级来解决线程的同步问题。</p>
<p>10) 处理器亲和，就是将线程固定在某cpu上执行，这样在某些情况下有助于提高性能，例如我们有双核的且支持超线程技术的cpu，我们有4个线程，有2个是IO操作，有2个是大量的计算，对于上面的问题，我们就可以使用处理器亲和，使用API设置，来达到cpu使用的均和，更好的提高性能。</p>
<p>11) 纤程，用户级的线程机制，比线程小的单位，开发人员负责管理纤程的调度，同时负责确定纤程何时在线程时间片上下文中运行，一般不会带来性能的提高，主要的目的是为开发人员调度多个不需要并行执行的任务提供一个便捷的机制。</p>
<p>12) 是否需要使用多线程，最总是需要测试来决定的，而且对于不同的CPU结果也不相同。避免使用过多的线程而带来性能下降。<br><br><br>其他多线程技术：</p>
<p>13) MFC多线程，多Windows多线程API的封装。</p>
<p>14) Boost多线程。</p>
<p>15) POSIX，Pthreads，是一个可以移植的多线程库。一般是Linux和Unix是商用较多。</p>
<p>16) Intel Open MP+，是一种可移植的多线程解决方案。（<a href="http://www.openmp.org/">www.openmp.org</a>）。<br><br><br></p>
<p>多线程调试：</p>
<p>17) 支持多线程的Log。</p>
<p>18) VS2005中，可以查看Thread窗口，挂起或恢复线程，切换当前的线程和检查线程状态。或是使用TracePoint来输出消息到output。</p>
<p>19)使用SetThreadName（）来对线程命名，使用线程信息block (<a href="http://www.codeproject.com/threads/xtib.asp">http://www.codeproject.com/threads/xtib.asp</a>)。</p>
<p>20) 使用Intel多线程线程检测器，Intel调试器。。。</p>
<p>&nbsp;</p><img src ="http://www.cppblog.com/mzty/aggbug/29155.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-08-02 09:59 <a href="http://www.cppblog.com/mzty/archive/2007/08/02/29155.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++多线程（九）</title><link>http://www.cppblog.com/mzty/archive/2007/08/01/28892.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Wed, 01 Aug 2007 07:38:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2007/08/01/28892.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/28892.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2007/08/01/28892.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/28892.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/28892.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 多线程之线程局部存储一 线程局部存储 （TLS）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 来自：http://msdn2.microsoft.com/en-us/library/ms686749.aspx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;同一进程中的所有线程共享相同的虚...&nbsp;&nbsp;<a href='http://www.cppblog.com/mzty/archive/2007/08/01/28892.html'>阅读全文</a><img src ="http://www.cppblog.com/mzty/aggbug/28892.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2007-08-01 15:38 <a href="http://www.cppblog.com/mzty/archive/2007/08/01/28892.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>