﻿<?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++博客-cloud-随笔分类-c++</title><link>http://www.cppblog.com/cloud/category/3696.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 05 Dec 2008 12:34:14 GMT</lastBuildDate><pubDate>Fri, 05 Dec 2008 12:34:14 GMT</pubDate><ttl>60</ttl><item><title>充分利用c/c++中的宏</title><link>http://www.cppblog.com/cloud/archive/2008/12/05/68628.html</link><dc:creator>cloud</dc:creator><author>cloud</author><pubDate>Fri, 05 Dec 2008 02:49:00 GMT</pubDate><guid>http://www.cppblog.com/cloud/archive/2008/12/05/68628.html</guid><wfw:comment>http://www.cppblog.com/cloud/comments/68628.html</wfw:comment><comments>http://www.cppblog.com/cloud/archive/2008/12/05/68628.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cloud/comments/commentRss/68628.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cloud/services/trackbacks/68628.html</trackback:ping><description><![CDATA[c/c++中的宏不是语法中的一部分， 是在编译器开始编译之前的一种文本替换行为， 因此可以利用c/c++中的编译器中的选项来预处理其他没有预处理功能的语言<br><br>比如， 利用微软的cl.exe 编译器来预处理文本， 命令： cl.exe /EP test.vb<br>这样如果test.vb中有类似#define 的语句， 会被删除， 而后一些用到该宏的地方， 会被真实的值替换
<img src ="http://www.cppblog.com/cloud/aggbug/68628.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cloud/" target="_blank">cloud</a> 2008-12-05 10:49 <a href="http://www.cppblog.com/cloud/archive/2008/12/05/68628.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】高效的XML——XDS</title><link>http://www.cppblog.com/cloud/archive/2008/11/12/66725.html</link><dc:creator>cloud</dc:creator><author>cloud</author><pubDate>Wed, 12 Nov 2008 07:34:00 GMT</pubDate><guid>http://www.cppblog.com/cloud/archive/2008/11/12/66725.html</guid><wfw:comment>http://www.cppblog.com/cloud/comments/66725.html</wfw:comment><comments>http://www.cppblog.com/cloud/archive/2008/11/12/66725.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cloud/comments/commentRss/66725.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cloud/services/trackbacks/66725.html</trackback:ping><description><![CDATA[<div>&#160;&#160; &#160;最近在游戏编程精粹4(Game Programming Gems 4)中看到了对于XDS的介绍，解开了我对于XML低效的困惑。也许在小型的XML应用中不觉得，但是在大数据量的应用中XML的速度甚至无法和普通的.ini相提并论。首先让我们来看看XDS是什么吧。</div><div>&#160;</div><div>&#160;&#160; &#160;XDS技术由DSD和XDS两种文件格式组成。前者跟XSD相似，后者跟XML相似，只不过这两种格式都是二进制的。正是采用了二进制格式，无论是在体积还是在速度上XDS的性能比XML都有明显的提升。目前支持XDS的免费库主要有XDSToolkit，现在可以下载到1.03版本。这是一个开源项目，解压后我们可以看到它由两个工具一个API包组成，另外还附一个例子。两个工具的名字分别叫做xdsConvert和xdsMakeSchema，分别是用来进行XML和XDS相互转换，以及生成DSD文件的。</div><div>&#160;</div><div>&#160;&#160; &#160;在一个C/C++项目中，我们经常需要用struct定义一系列数据结构。xdsMakeSchema就可以通过输入数据结构的定义文件.h来生成DSD和相应的c头文件。在一个项目的初期，你可能需要用XML编辑器来编写这个项目所需要的XML数据，然后在程序中通过XDSLiteAPI来进行解析。这套API有两个Paser，一个服务于XML，另一个服务于XDS。当你的项目完全可以自动生成XML的时候就可以由XML转向XDS了。游戏编程精粹中解释的很详细，这边就说说需要注意的地方了。</div><div>&#160;</div><div>&#160;&#160; &#160;要利用API对XDS进行解析需要以下步骤：</div><div>① &#160; &#160; 以struct定义的C数据类型</div><div>② &#160; &#160; XDS的数据类型定义，可以在DSD中，也可以在程序中定义</div><div>③ &#160; &#160; 回调函数的编写，主要是XDS_PROCESSNODE函数</div><div>&#160;</div><div>以该工具包附带的Powerup为例，struct看起来是这样的：</div><div>struct PowerUp_t {</div><div>&#160;&#160; &#160;char szName[10]; &#160; &#160; &#160; &#160;// display name</div><div>&#160;&#160; &#160;char szImage[16]; &#160; &#160; &#160; // image file name</div><div>&#160;</div><div>&#160;&#160; &#160;// health increase/decrease (-128 to 127)</div><div>&#160;&#160; &#160;signed char &#160; iHealth;</div><div>&#160;</div><div>&#160;&#160; &#160;// temporary abilities/penalties</div><div>&#160;&#160; &#160;// (value is duration in seconds)</div><div>&#160;&#160; &#160;unsigned char iInvulnerability;</div><div>&#160;&#160; &#160;unsigned char iFastMove;</div><div>&#160;&#160; &#160;unsigned char iHighJump;</div><div>&#160;&#160; &#160;unsigned char iStunPlayer;</div><div>&#160;</div><div>&#160;&#160; &#160;// extra life (count)</div><div>&#160;&#160; &#160;unsigned char iLifeUp;</div><div>};</div><div>&#160;</div><div>// global power-up definition cache</div><div>extern struct PowerUp_t *g_PowerUps;</div><div>&#160;</div><div>可以通过使用xdsMakeSchema来生成dsd，同时生成的xxxx_dsd.h只是为了免除将dsd文件读入内存，查看它的内容就可以看到它定义了一个dsd数组：</div><div>// XDS DSD literal -- use this in calls to xdsInit()</div><div>//</div><div>#ifdef DEFINE_DSD</div><div>&#160;</div><div>const unsigned char XDSDSD_Powerups[216] = {</div><div>&#160;&#160; &#160;0x58, 0x44, 0x53, 0x21, 0x30, 0x33, 。。。</div><div>};</div><div>&#160;</div><div>#else</div><div>&#160;</div><div>extern const unsigned char XDSDSD_Powerups[216];</div><div>&#160;</div><div>#endif</div><div>&#160;</div><div>&#160;</div><div>// XDS DSD IDs -- use these in implementation of XDS_PROCESSNODE()</div><div>//</div><div>#define XDS_Powerups_Powerup &#160; &#160;0x0100 // Record</div><div>#define XDS_Powerups_PowerUp_t 0x0101 // Type</div><div>#define XDS_Powerups__xdsType1 0x0102 // Type</div><div>#define XDS_Powerups_g_PowerUps 0x0103 // Element</div><div>&#160;</div><div>同时还定义了一些常量，这些常量在解析xds中会用到。</div><div>除了在dsd中对于xds格式的定义之外，我们还可以在main.cpp中看到程序内的定义：</div><div>#ifdef XDS_SUPPORT_DEFTYPE</div><div>void regDsd(struct xdsHandle *hXds)</div><div>{</div><div>&#160;&#160; &#160;// Register my types (test only)</div><div>&#160;</div><div>&#160;&#160; &#160;xdsDefRecord(hXds, "Powerup", 2);</div><div>&#160;</div><div>&#160;&#160; &#160;unsigned short iStructType = xdsDefStructType(hXds, "PowerUp_t");</div><div>&#160;&#160; &#160;xdsDefStructField(hXds, iStructType, "szName", XDS_TYPE_CHAR, 10);</div><div>&#160;&#160; &#160;xdsDefStructField(hXds, iStructType, "szImage", XDS_TYPE_CHAR, 16);</div><div>&#160;&#160; &#160;xdsDefStructField(hXds, iStructType, "iHealth", XDS_TYPE_CHAR, 0);</div><div>xdsDefStructField(hXds, iStructType, "iInvulnerability", XDS_TYPE_BYTE, 0);</div><div>&#160;&#160; &#160;xdsDefStructField(hXds, iStructType, "iFastMove", XDS_TYPE_BYTE, 0);</div><div>&#160;&#160; &#160;xdsDefStructField(hXds, iStructType, "iHighJump", XDS_TYPE_BYTE, 0);</div><div>&#160;&#160; &#160;xdsDefStructField(hXds, iStructType, "iStunPlayer", XDS_TYPE_BYTE, 0);</div><div>&#160;&#160; &#160;xdsDefStructField(hXds, iStructType, "iLifeUp", XDS_TYPE_BYTE, 0);</div><div>&#160;</div><div>&#160;&#160; &#160;xdsDefStructDone(hXds, iStructType);</div><div>&#160;&#160; &#160;unsigned short iArrayType = xdsDefArrayType(hXds, "_xdsType1", iStructType, 0, 2);</div><div>&#160;</div><div>&#160;&#160; &#160;xdsDefElement(hXds, "g_PowerUps", iArrayType, 0);</div><div>}</div><div>#endif</div><div>&#160;</div><div>&#160;&#160; &#160;注意：交叉使用dsd定义和程序定义容易造成一个错误，就是在程序和dsd可能在定义的时候冲突，数据类型冲突，或者数据长度冲突，从而导致程序的崩溃。附带的例子中程序定义数据类型如下：</div><div>#ifdef XDS_SUPPORT_DEFTYPE</div><div>void regDsd(struct xdsHandle *hXds)</div><div>{</div><div>&#160;&#160; &#160;// Register my types (test only)</div><div>&#160;</div><div>&#160;&#160; &#160;xdsDefRecord(hXds, "Powerup", 4);</div><div>&#160;</div><div>&#160;&#160; &#160;unsigned short iStructType = xdsDefStructType(hXds, "PowerUp_t");</div><div>&#160;&#160; &#160;xdsDefStructField(hXds, iStructType, "szName", XDS_TYPE_CHAR, 10);</div><div>&#160;&#160; &#160;xdsDefStructField(hXds, iStructType, "szImage", XDS_TYPE_CHAR, 16);</div><div>&#160;&#160; &#160;xdsDefStructField(hXds, iStructType, "iHealth", XDS_TYPE_CHAR, 0);</div><div>&#160;&#160; &#160;xdsDefStructField(hXds, iStructType, "iInvulnerability", XDS_TYPE_BYTE, 0);</div><div>&#160;&#160; &#160;xdsDefStructField(hXds, iStructType, "iFastMove", XDS_TYPE_BYTE, 0);</div><div>&#160;&#160; &#160;xdsDefStructField(hXds, iStructType, "iHighJump", XDS_TYPE_BYTE, 0);</div><div>&#160;&#160; &#160;xdsDefStructField(hXds, iStructType, "iStunPlayer", XDS_TYPE_BYTE, 0);</div><div>&#160;&#160; &#160;xdsDefStructField(hXds, iStructType, "iLifeUp", XDS_TYPE_BYTE, 0);</div><div>&#160;</div><div>&#160;&#160; &#160;xdsDefStructDone(hXds, iStructType);</div><div>&#160;&#160; &#160;unsigned short iArrayType = xdsDefArrayType(hXds, "_xdsType1", iStructType, 0, 2);</div><div>&#160;</div><div>&#160;&#160; &#160;xdsDefElement(hXds, "g_PowerUps", iArrayType, 0);</div><div>}</div><div>#endif</div><div>&#160;</div><div>要是在生成dsd时用参数-r Powerup:2而这里用xdsDefRecord(hXds, "Powerup", 4)的话就会导致冲突。</div>
<img src ="http://www.cppblog.com/cloud/aggbug/66725.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cloud/" target="_blank">cloud</a> 2008-11-12 15:34 <a href="http://www.cppblog.com/cloud/archive/2008/11/12/66725.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]游戏Entity设计不完全整理</title><link>http://www.cppblog.com/cloud/archive/2008/01/09/40796.html</link><dc:creator>cloud</dc:creator><author>cloud</author><pubDate>Wed, 09 Jan 2008 07:14:00 GMT</pubDate><guid>http://www.cppblog.com/cloud/archive/2008/01/09/40796.html</guid><wfw:comment>http://www.cppblog.com/cloud/comments/40796.html</wfw:comment><comments>http://www.cppblog.com/cloud/archive/2008/01/09/40796.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cloud/comments/commentRss/40796.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cloud/services/trackbacks/40796.html</trackback:ping><description><![CDATA[<div class=postText>
<p class=MsoNormal style="TEXT-ALIGN: center"><span style="FONT-FAMILY: 宋体"><span style="FONT-FAMILY: 宋体"><span style="FONT-FAMILY: 宋体">在游戏引擎中，</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">通常被翻译成实体，也常用诸如</span><span lang=EN-US>GameObject</span><span style="FONT-FAMILY: 宋体">、</span><span lang=EN-US>Actor</span><span style="FONT-FAMILY: 宋体">、</span><span lang=EN-US>SimulationObject</span><span style="FONT-FAMILY: 宋体">、</span><span lang=EN-US>Unit</span><span style="FONT-FAMILY: 宋体">、</span><span lang=EN-US>Character</span><span style="FONT-FAMILY: 宋体">等名字。相比于对图像声音引擎的热情，</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">层多年来一直备受冷遇，但最近几年随着大型游戏的发展，</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">层设计的重要性已经达到和图像声音的同等水平，而且已经出现了多种通用型</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">架构。当然，这里伴随着争议和分歧。</span></p>
<h3><span style="FONT-FAMILY: 宋体">直接模式（</span><span lang=EN-US>The C Approach</span><span style="FONT-FAMILY: 宋体">）</span></h3>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">这是最早、最简单、也是任何人都能直接想到的模式。这种方式下一个</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">就是一个简单的</span><span lang=EN-US>struct:</span></p>
<p class=MsoNormal><span lang=EN-US>struct Mob<br>{<br>int level, hp, mp, attack, &#8230;;<br>};</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">这种情况下往往需要对不同类型的</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">定义不同的</span><span lang=EN-US>struct</span><span style="FONT-FAMILY: 宋体">，比如</span><span lang=EN-US>Player</span><span style="FONT-FAMILY: 宋体">、</span><span lang=EN-US>Mob</span><span style="FONT-FAMILY: 宋体">、</span><span lang=EN-US>Item</span><span style="FONT-FAMILY: 宋体">、</span><span lang=EN-US>Doodad</span><span style="FONT-FAMILY: 宋体">等。</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">的数据库可以直接使用现成的数据库系统或者从数据文件读取，比如</span><span lang=EN-US>csv</span><span style="FONT-FAMILY: 宋体">文件。一般会选择</span><span lang=EN-US>Excel</span><span style="FONT-FAMILY: 宋体">编辑数据库，然后导出</span><span lang=EN-US>csv</span><span style="FONT-FAMILY: 宋体">。</span><span lang=EN-US>Excel</span><span style="FONT-FAMILY: 宋体">的强大表格和统计计算功能是调节游戏数据平衡的得力工具。以致这种最古老而简单的</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">模式以强大的生命力一直活到现在。</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">那么为什么</span><span lang=EN-US>Developers</span><span style="FONT-FAMILY: 宋体">会要去探索其他方式呢？最大的问题是这种方式下各种</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">完全不同质。比如</span><span lang=EN-US>Player</span><span style="FONT-FAMILY: 宋体">、</span><span lang=EN-US>Mob</span><span style="FONT-FAMILY: 宋体">、</span><span lang=EN-US>Doodad</span><span style="FONT-FAMILY: 宋体">都有位置，都要做碰撞检测，但他们却是不同的类型，不能使用同一份代码；</span><span lang=EN-US>Player</span><span style="FONT-FAMILY: 宋体">和</span><span lang=EN-US>Mob</span><span style="FONT-FAMILY: 宋体">都有</span><span lang=EN-US>hp</span><span style="FONT-FAMILY: 宋体">和</span><span lang=EN-US>mp</span><span style="FONT-FAMILY: 宋体">，也有基本相同的处理逻辑&#8230;&#8230;当然，这个可以用</span><span lang=EN-US>hack</span><span style="FONT-FAMILY: 宋体">的方法解决：只要各个</span><span lang=EN-US>struct</span><span style="FONT-FAMILY: 宋体">前若干个成员类型和顺序完全相同，就可以将指针</span><span lang=EN-US>cast</span><span style="FONT-FAMILY: 宋体">成统一的一个</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">类型来处理。不过，任何人都能想到更好的办法，用类！</span></p>
<h3><span style="FONT-FAMILY: 宋体">继承模式（</span><span lang=EN-US>Inheritage</span><span style="FONT-FAMILY: 宋体">）</span></h3>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">这也是</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">、</span><span lang=EN-US>GameObject</span><span style="FONT-FAMILY: 宋体">等这些名字的由来，他们就是基类。于是我们可以得到一颗继承关系树，例如：</span></p>
<p class=MsoNormal><span lang=EN-US>Entity</span></p>
<p class=MsoNormal><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Character</span></p>
<p class=MsoNormal><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Player</span></p>
<p class=MsoNormal><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Mob</span></p>
<p class=MsoNormal><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Missile</span></p>
<p class=MsoNormal><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Laser</span></p>
<p class=MsoNormal><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>GuidedMissile</span></p>
<p class=MsoNormal><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Item</span></p>
<p class=MsoNormal><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&#8230;</span></p>
<p class=MsoNormal><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">对象的逻辑大多也是直接包含在类里的。但也有人采用了数据对象和逻辑对象的分离，其好处是对相同的数据可以替换不同的逻辑。不过，个人比较怀疑这种分离是否值得，因为类的派生本身就是可以拥有不同的逻辑。</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">另外，</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">间的交互除了用标准的直接访问方式外，经常使用消息模式。消息模式和</span><span lang=EN-US>Windows</span><span style="FONT-FAMILY: 宋体">的消息模式类似，</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">间通过消息交互。虽说窗口编程画了多年时间才摆脱了当年肥大的</span><span lang=EN-US>switch</span><span style="FONT-FAMILY: 宋体">的消息处理模式，在</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">层使用消息模式还是有意义的，因为消息很容易广播且可以直接在网络上发送。执着于</span><span lang=EN-US>OO</span><span style="FONT-FAMILY: 宋体">的人会将消息写成</span><span lang=EN-US>Command</span><span style="FONT-FAMILY: 宋体">对象，但原理仍然是一样的。</span><span lang=EN-US><o:p></o:p></span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">同时，联网游戏出现，指针不能在不同的机器上标识对象，我们必须用稳定的</span><span lang=EN-US>ID</span><span style="FONT-FAMILY: 宋体">来标识对象，于是我们有了</span><span lang=EN-US>EntityManager</span><span style="FONT-FAMILY: 宋体">来分配</span><span lang=EN-US>ID</span><span style="FONT-FAMILY: 宋体">和管理对象集合，或者叫</span><span lang=EN-US>GameObjectManager</span><span style="FONT-FAMILY: 宋体">、</span><span lang=EN-US>ObjectManager</span><span style="FONT-FAMILY: 宋体">等。这在一段时期内几乎成了完美的方案。</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">随着游戏内容的丰富性的迅速膨胀，传统的由程序员来实现游戏逻辑功能的模式也越来越力不从心。脚本语言的集成将大部分创意性工作从程序员的担子上拿了下来，交还给游戏设计人员。为了给脚本提供足够的控制权，</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">结构上必须有充分的灵活性。</span></p>
<h3><span style="FONT-FAMILY: 宋体">数据驱动（</span><span lang=EN-US>Data-Driven</span><span style="FONT-FAMILY: 宋体">）</span></h3>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">现在有句很流行的话，&#8220;唯一不变的是变化。（</span><span lang=EN-US>The only constant is change.</span><span style="FONT-FAMILY: 宋体">）&#8221;数据驱动使得变化对引擎的影响最小化。数据驱动不能算是一种独立的</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">模式，不如说它是一种设计思想，其目的就是将内容制作和游戏引擎的制作分离开来。与上面所说的填充</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">属性数据库的不同之处在于，它还要能通过数据来设计游戏逻辑。</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">游戏设计人员需要的一项最基本功能就是自定义人物属性，所以与其在类里写死属性成员，不如使用属性表（</span><span lang=EN-US>Attributes/Properties</span><span style="FONT-FAMILY: 宋体">）。通常使用一个哈希表（</span><span lang=EN-US>Hashtable</span><span style="FONT-FAMILY: 宋体">），或者</span><span lang=EN-US>std::map</span><span style="FONT-FAMILY: 宋体">，或者</span><span lang=EN-US>Dictionary</span><span style="FONT-FAMILY: 宋体">，或者就是个数组，随个人喜好，其实就是要一个</span><span lang=EN-US>key-value</span><span style="FONT-FAMILY: 宋体">的映射表。然后为脚本和编辑器提供对属性表的操作。</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">动态的逻辑主要就靠脚本了，必须为脚本提供足够的事件和方法。个人推荐用</span><span lang=EN-US>Lua</span><span style="FONT-FAMILY: 宋体">脚本，因为它是在游戏领域内用得最多的通用脚本语言，其引擎很小、速度很快、易于集成，尽管语法过于松散。不要迷信宣传去用庞大、极慢、难于集成的</span><span lang=EN-US>Python</span><span style="FONT-FAMILY: 宋体">。为脚本提供事件，其实也就是调用脚本里的函数，这里如果使用了前面所述的消息模式，那么就只要调用一个脚本方法，传递不同的消息参数就行了。当然也有人觉得这样很丑陋而更愿意为不同的事件注册不同的函数。</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">当有了数据驱动后，</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">的继承树就基本失去意义了，因为一个</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">是什么已经不是程序里决定的了，而是通过数据和脚本设计出来的。但数据和脚本又不是全部，一个</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">的核心内容和需要高效处理的部分，如碰撞检测，还是要程序来完成。于是我们需要重新设计</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">类，困难的局面也就由此开始。</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">一个直观的想法是一个统一且唯一的</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">类，它包含了所有的基本功能，如显示、碰撞检测、运动、背包等，然后由数据决定哪些组件被启用。比如一个玩家角色可能会启用绝大部分组件，而一颗树只启用显示和碰撞检测组件。但也伴随着缺点：一、这个类太大了；二、对于树木等一些简单的</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">也要浪费其他组件的私有数据所占的内存。那么一个简单的折中是部分使用继承、部分使用数据定制。例如</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">只提供最基本的组件，再派生出</span><span lang=EN-US>CharactorEntity</span><span style="FONT-FAMILY: 宋体">提供足够人物角色使用的组件。</span></p>
<h3><span style="FONT-FAMILY: 宋体">组件模式（</span><span lang=EN-US>Component-Based Entity</span><span style="FONT-FAMILY: 宋体">）</span></h3>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">提到组件，那么很自然的就过渡到组件模式，就是把显示、运动、攻击、背包、队伍、声音等基本功能都做成独立的组件，由数据来决定向</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">里添加哪些组件。由此可以得到另外一个扩展，就是既然可以有引擎内置的组件，那就也可以有脚本制作的组件，实现脚本模块的复用。这种模式在</span><span lang=EN-US>GDC2002</span><span style="FONT-FAMILY: 宋体">正式提出，到现在主流的引擎都有这种设计。</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">这种模式在理论上很完美，但实践上还是有不少疑问。最常见的问题就是组件间的依赖关系。理想情况下，各个组件是完全独立的，但实践中必然有所依赖。比如运动速度、攻击强度等和角色的基本属性有关，运动组件需要角色的包围盒来测试是否碰撞，</span><span lang=EN-US>AI</span><span style="FONT-FAMILY: 宋体">组件需要分析角色当前状态和发出运动、攻击命令，角色动作状态变化时改变显示组件属性，攻击组件需要访问队伍信息组件以禁止攻击队友等等。处理这种依赖关系主要要解决两个问题：</span></p>
<p class=MsoNormal style="MARGIN-LEFT: 19.5pt; TEXT-INDENT: -19.5pt">&lt;!--[if !supportLists]--&gt;<span lang=EN-US><span>一、<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span>&lt;!--[endif]--&gt;<span style="FONT-FAMILY: 宋体">谁依赖谁。比如是敏捷属性改变而去修改移动速度，还是运动组件读取敏捷属性来计算移动速度。如果要游戏设计人员自由定义基本属性的话，就要选择前者，因为基本属性组件会是脚本组件。</span></p>
<p class=MsoNormal style="MARGIN-LEFT: 19.5pt; TEXT-INDENT: -19.5pt">&lt;!--[if !supportLists]--&gt;<span lang=EN-US><span>二、<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span>&lt;!--[endif]--&gt;<span style="FONT-FAMILY: 宋体">如何取得另一组件的指针</span><span lang=EN-US>/</span><span style="FONT-FAMILY: 宋体">引用。常见的方法是给每个组件类型一个唯一</span><span lang=EN-US>ID</span><span style="FONT-FAMILY: 宋体">，然后用该</span><span lang=EN-US>ID</span><span style="FONT-FAMILY: 宋体">在</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">上查询注册了的组件，如果找到返回其指针</span><span lang=EN-US>/</span><span style="FONT-FAMILY: 宋体">引用，否则返回</span><span lang=EN-US>null</span><span style="FONT-FAMILY: 宋体">。当然，每次访问都做这个查询会很浪费</span><span lang=EN-US>CPU</span><span style="FONT-FAMILY: 宋体">，如果</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">的组件不会在运行时动态添加删除的话（除非在编辑器里，否则很少有人会这么做），可以在</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">初始化后让每个组件缓存它所要用的其他组件指针。那么当所依赖的组件不存在怎么办，一般情况下都是无声地忽略。</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">当</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">由很多组件组成后，交互的消息需要发给每一个组件。这里又一次体现出消息机制的优势，你不需要在</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">里为每一个事件函数写一个</span><span lang=EN-US>loop</span><span style="FONT-FAMILY: 宋体">来调用组件的相应事件函数。但这里也出现了一个问题，消息到达各个组件的顺序。很多时候这个顺序不会有什么影响，但个别时候不同的顺序会导致完全不同的逻辑发展方向。</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">此外，</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">的序列化存储也变得比较复杂，经典的</span><span lang=EN-US>Excel</span><span style="FONT-FAMILY: 宋体">导出</span><span lang=EN-US>csv</span><span style="FONT-FAMILY: 宋体">的模式难以奏效，因为这里需要结构化的存储，所以需要结构化的数据文件如</span><span lang=EN-US>XML</span><span style="FONT-FAMILY: 宋体">来存储，或者完全用脚本来包含所有数据和构造</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">。</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">据个人经验，使用数据驱动的继承模式时很是向往组件模式，感觉上它一个非常自然的扩展方向，但顾忌其引入的额外的复杂性，尤其是需要游戏设计人员具有一定的编程能力，所以一直不敢全盘接过使用。但退一步，在引擎里仍然使用组件思想，但</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">的组件构成在编译时固定，可以达到某种妥协，这和采用继承与数据驱动的折中类似。</span></p>
<h3><span style="FONT-FAMILY: 宋体">混入模式（</span><span lang=EN-US>Mix-in</span><span style="FONT-FAMILY: 宋体">）</span></h3>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">这是又一种常见的折中模式，即使用</span><span lang=EN-US>C++</span><span style="FONT-FAMILY: 宋体">的多重继承，将各个组件类混入一个</span><span lang=EN-US>Entity</span><span style="FONT-FAMILY: 宋体">类。如：</span></p>
<p class=MsoNormal><span lang=EN-US>class Mob: public GameObject, public Renderable, public Movable, public Attackable<br>{<br>&#8230;<br>}</span></p>
<p class=MsoNormal><span lang=EN-US><o:p></o:p></span><span style="FONT-FAMILY: 宋体">这种方法因其简单而且非常符合多重继承设计思想而被很多引擎采用。当然缺点也是只能在支持多重继承的语言里使用，而且当组件很丰富时，</span><span lang=EN-US>dynamic_cast</span><span style="FONT-FAMILY: 宋体">就变成一个代价高昂的操作。</span><span lang=EN-US><o:p> <br></o:p></span></p>
<h3><span style="FONT-FAMILY: 宋体">功能性与复杂性（</span><span lang=EN-US>Functionality vs Complexity</span><span style="FONT-FAMILY: 宋体">）</span></h3>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">编程领域最古老的原则之一就是要&#8220;简单快速&#8221;。但随着问题的复杂化，程序也随之变得越来越复杂。好的方法应该能有效的降低或隐藏复杂性。但是，没有不带副作用的药（</span><span lang=EN-US>No silver bullet.</span><span style="FONT-FAMILY: 宋体">），在取得更强大的功能的同时总会带来额外的复杂性。我们需要做出权衡，在必要时牺牲一些功能，也就是要估算性价比。</span><br><span lang=EN-US><o:p></o:p></span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">一般游戏内容制作人员不会或不太会编程，编程人员也不善于游戏的内容创造和数值平衡，过于复杂的系统会导致需要两面兼顾的人才，会大大增加做出一款游戏的难度。</span></p>
</span></span></div>
<img src ="http://www.cppblog.com/cloud/aggbug/40796.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cloud/" target="_blank">cloud</a> 2008-01-09 15:14 <a href="http://www.cppblog.com/cloud/archive/2008/01/09/40796.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vc++2005中的异常</title><link>http://www.cppblog.com/cloud/archive/2007/11/29/37511.html</link><dc:creator>cloud</dc:creator><author>cloud</author><pubDate>Thu, 29 Nov 2007 12:41:00 GMT</pubDate><guid>http://www.cppblog.com/cloud/archive/2007/11/29/37511.html</guid><wfw:comment>http://www.cppblog.com/cloud/comments/37511.html</wfw:comment><comments>http://www.cppblog.com/cloud/archive/2007/11/29/37511.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cloud/comments/commentRss/37511.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cloud/services/trackbacks/37511.html</trackback:ping><description><![CDATA[vc++2005中的异常捕获try...catch... 和以往的版本有很大的不同, 默认的vc++2005的工程只能捕获由throw抛出的异常, 当然, 如果是用windows的__try...__except, 可以捕获到结构化异常的, 如果想让try...catch...捕获结构化异常, 那么就需要设置为/EHA, 而不是/EHS
<img src ="http://www.cppblog.com/cloud/aggbug/37511.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cloud/" target="_blank">cloud</a> 2007-11-29 20:41 <a href="http://www.cppblog.com/cloud/archive/2007/11/29/37511.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>lua的远程调试</title><link>http://www.cppblog.com/cloud/archive/2007/10/20/34673.html</link><dc:creator>cloud</dc:creator><author>cloud</author><pubDate>Sat, 20 Oct 2007 04:18:00 GMT</pubDate><guid>http://www.cppblog.com/cloud/archive/2007/10/20/34673.html</guid><wfw:comment>http://www.cppblog.com/cloud/comments/34673.html</wfw:comment><comments>http://www.cppblog.com/cloud/archive/2007/10/20/34673.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cloud/comments/commentRss/34673.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cloud/services/trackbacks/34673.html</trackback:ping><description><![CDATA[这几天一直在找lua的远程调试， 终于找到一个LuaPlus和remdebug， 在此做个标记
<img src ="http://www.cppblog.com/cloud/aggbug/34673.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cloud/" target="_blank">cloud</a> 2007-10-20 12:18 <a href="http://www.cppblog.com/cloud/archive/2007/10/20/34673.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]C++资源之不完全导引（完整版） </title><link>http://www.cppblog.com/cloud/archive/2007/05/25/24835.html</link><dc:creator>cloud</dc:creator><author>cloud</author><pubDate>Fri, 25 May 2007 08:39:00 GMT</pubDate><guid>http://www.cppblog.com/cloud/archive/2007/05/25/24835.html</guid><wfw:comment>http://www.cppblog.com/cloud/comments/24835.html</wfw:comment><comments>http://www.cppblog.com/cloud/archive/2007/05/25/24835.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cloud/comments/commentRss/24835.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cloud/services/trackbacks/24835.html</trackback:ping><description><![CDATA[<table class="fixedTable blogpost" cellSpacing=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=ellipse><span class=bvTitle id=subjcns!1p5qP-LmQlonNx_ujZCY3OgA!128><strong><font size=3>C++资源之不完全导引（完整版）</font> </strong></span></td>
        </tr>
        <tr>
            <td class=bvh8><strong><font size=3></font></strong></td>
        </tr>
        <tr>
            <td id=msgcns!1p5qP-LmQlonNx_ujZCY3OgA!128>
            <p>C++资源之不完全导引（完整版）</p>
            <p>来源：<a href="http://www.csdn.net/"><u><font color=#0000ff>www.csdn.net</font></u></a></p>
            <p>撰文：曾毅、陶文</p>
            <p>声明：本文2004年5月首发于《CSDN开发高手》，版权归该杂志与《程序员》杂志社<br>所有。</p>
            <p>------------------------------------------------------------------------<br>--------</p>
            </td>
        </tr>
    </tbody>
</table>
<p>　　1，前言</p>
<p>　　无数次听到&#8220;我要开始学习C++!&#8221;的呐喊，无数次听到&#8220;C++太复杂了，我真的<br>学不会&#8221;的无奈。Stan Lippman先生曾在《C++ Primer》一书中指出&#8220;C++是最为难<br>学的高级程序设计语言之一&#8221;，人们常将&#8220;之一&#8221;去掉以表达自己对C++的敬畏。诚<br>然，C++程序设计语言对于学习者的确有很多难以逾越的鸿沟，体系结构的庞大，应<br>接不暇并不断扩充的特性&#8230;&#8230;除此之外，参考资料之多与冗杂使它的学习者望而却<br>步，欲求深入者苦不堪言。希望这一份不完全导引能够成为您C++学习之路上的引路<br>灯。</p>
<p>　　撰写本文的初衷并不打算带领大家体验古老的C++历史，如果你想了解C++的历<br>史与其前期发展中诸多技术的演变，你应当去参考Bjarne的《The Design and Evo<br>lution of C++》。当然也不打算给大家一个无所不包的宝典（并非不想：其一是因<br>水平有限，其二无奈C++之博大精深），所给出的仅仅是一些我们认为对于想学习C<br>++的广大读者来说最重要并且触手可及的开发与学习资源。</p>
<p>　　本文介绍并分析了一些编译器，开发环境，库，少量的书籍以及参考网站，并<br>且尽可能尝试着给出一个利用这些资源的导引，望对如同我们一样的初学者能够有<br>所裨益。</p>
<p>------------------------------------------------------------------------<br>--------</p>
<p>　　2，编译器</p>
<p>　　在C++之外的任何语言中，编译器都从来没有受到过如此之重视。因为C++是一<br>门相当复杂的语言，所以编译器也难于构建。直到最近我们才开始能够使用上完全<br>符合C++标准的编译器（哦，你可能会责怪那些编译器厂商不能尽早的提供符合标准<br>的编译器，这只能怪他们各自维系着自身的一套别人不愿接受的标准）。什么？你<br>说这无关紧要？哦，不，你所需要的是和标准化C++高度兼容的编译环境。长远来看<br>，只有这样的编译器对C++开发人员来说才是最有意义的工具，尤其是对于程序设计<br>语言的学习者。一至性让代码具备可移植性，并让一门语言及其库的应用更为广泛<br>。嗯，是的，我们这里只打算介绍一些公认的优秀编译器。</p>
<p>　　2.1 Borland C++</p>
<p>　　这个是Borland C++ Builder和Borland C++ Builder X这两种开发环境的后台<br>编译器。（哦，我之所以将之分为两种开发环境你应当能明白为什么，正如Delphi<br>7到Delphi8的转变，是革命性的两代。）Borland C++由老牌开发工具厂商Borland<br>倾力打造。该公司的编译器素以速度快，空间效率高著称，Borland C++ 系列编译<br>器秉承了这个传统，属于非常优质的编译器。标准化方面早在5.5版本的编译器中对<br>标准化C++的兼容就达到了92.73%。目前最新版本是Borland C++ Builder X中的6.<br>0版本，官方称100%符合ANSI/ISO的C++标准以及C99标准。嗯&#8230;这正是我前面所指的<br>&#8220;完全符合C++标准的编译器&#8221;。</p>
<p>　　2.2 Visual C++</p>
<p>　　这个正是我们熟知的Visual Studio 和 Visual Studio.net 2002, 2003以及2<br>005 Whidbey中带的C++编译器。由Microsoft公司研制。在Visual Studio 6.0中，<br>因为编译器有太多地方不能与后来出现的C++标准相吻合而饱受批评（想想你在使用<br>STL的时候编译时报出的那些令人厌恶的error和warning吧）。VC++6.0对标准化C+<br>+的兼容只有83.43%。但是随着C++编译器设计大师Stanley Lippman以及诸多C++社<br>群达人的加盟，在Visual Studio.NET 2003中，Visual C++编译器已经成为一个非<br>常成熟可靠的C++编译器了。Dr.Dobb's Journal的评测显示Visual C++7.1对标准C<br>++的兼容性高达98.22%，一度成为CBX之前兼容性最好的编译器。结合强大的Visua<br>l Studio.NET开发环境，是一个非常不错的选择。至于Whidbey时代的Visual C++,<br>似乎微软所最关注的是C++/CLI&#8230;&#8230;我们不想评论微软下一代的C++编译器对标准化<br>兼容如何，但他确实越来越适合.NET (其实你和我的感觉可能是一样的，微软不应<br>当把标准C++这块肥肉丢给Borland,然而微软可能并不这样认为)。</p>
<p>　　2.3 GNU C++</p>
<p>　　著名的开源C++编译器。是类Unix操作系统下编写C++程序的首选。特点是有非<br>常好的移植性，你可以在非常广泛的平台上使用它，同时也是编写跨平台，嵌入式<br>程序很好的选择。另外在符合标准这个方面一直都非常好，GCC3.3大概能够达到96<br>.15%。但是由于其跨平台的特性，在代码尺寸速度等优化上略微差一点。</p>
<p>　　基于GNU C++的编译器有很多，比如：</p>
<p>　　(1) Mingw</p>
<p>　　<a href="http://www.mingw.org/"><u><font color=#0000ff>http://www.mingw.org/</font></u></a></p>
<p>　　GCC的一个Windows的移植版本（Dev-C++的后台）</p>
<p>　　(2) Cygwin</p>
<p>　　<a href="http://sources.redhat.com/cygwin/"><u><font color=#0000ff>http://sources.redhat.com/cygwin/</font></u></a></p>
<p>　　GCC的另外一个Windows移植版本是Cygwin的一部分，Cygwin是Windows下的一个<br>Unix仿真环境。严格的说是模拟GNU的环境，这也就是"Gnu's Not Unix"要表达的意<br>思，噢，扯远了，这并不是我们在这里关心的实质内容。</p>
<p>　　(3) Djgpp</p>
<p>　　<a href="http://www.delorie.com/djgpp/"><u><font color=#0000ff>http://www.delorie.com/djgpp/</font></u></a></p>
<p>　　这是GCC的DOS移植版本。</p>
<p>　　(4) RSXNT</p>
<p>　　<a href="http://www.mathematik.uni-bielefeld.de/~rainer/"><u><font color=#0000ff>http://www.mathematik.uni-bielefeld.de/~rainer/</font></u></a></p>
<p>　　这是GCC的DOS和Windows移植版本。</p>
<p>　　(5) Intel C++</p>
<p>　　著名CPU制造厂商Intel出品的编译器，Special Design for Intel x86！对于<br>Intel x86结构的CPU经过特别的优化。在有些应用情况下，特别是数值计算等高性<br>能应用，仅仅采用Intel的编译器编译就能大幅度的提高性能。</p>
<p>　　(6) Digital Mars C++</p>
<p>　　网络上提供免费下载，Zortech/Symantec C++的继承者，其前身在当年惨烈的<br>C++四国战中也是主角之一。</p>
<p>------------------------------------------------------------------------<br>--------</p>
<p>　　3，开发环境</p>
<p>　　开发环境对于程序员的作用不言而喻。选择自己朝夕相处的环境也不是容易的<br>事情，特别是在IDE如此丰富的情况下。下面就是我们推荐的一些常见的C++开发环<br>境，并没有包括一些小型的，罕见的IDE。其中任何一款都是功能丰富，可以用作日<br>常开发使用的。对于不同层面的开发者，请参见内文关于适用对象的描述。</p>
<p>　　3.1 Visual Studio 6.0</p>
<p>　　这个虽然是Microsoft公司的老版本的开发环境，但是鉴于其后继版本Visual<br>Studio.NET的庞大身躯，以及初学者并不那么高的功能要求，所以推荐这个开发环<br>境给C++的初学者，供其学习C++的最基本的部分，比如C的那部分子集，当然你别指<br>望他能够支持最新的C99标准。在日常的开发中，仍然有很多公司使用这个经典稳定<br>的环境，比如笔者就看曾亲见有些公司将其编译器替换为GCC做手机开发之用。</p>
<p>　　3.2 Visual Studio.NET 2003</p>
<p>　　作为Microsoft公司官方正式发布的最新版本开发环境，其中有太多激动人心的<br>功能。结合其最新的C++编译器。对于机器配置比较好的开发人员来说，使用这个开<br>发环境将能满足其大部分的要求。这里不打算单独说Visual Studio Whidbey,虽然<br>Visual Studio .NET 2005 - Whidbey社区预览版已经推出，但暂不是很稳定，读者<br>可以亲身去体验。</p>
<p>　　3.3 Borland C++ Builder 6</p>
<p>　　这个并不是Borland的C++开发环境的最新版本。选择它的原因是它不是用Java<br>写的IDE，速度比较快。它有一个很完善的GUI窗体设计器，和Delphi共用一个VCL。<br>由于这些特点，比较适合初学者上手。但是由于其GUI的中心位置，可能不利于对于<br>C++语言的学习。而且其为了支持VCL这个Object Pascal写的库也对C++进行了一些<br>私有的扩充。使得人们有一个不得不接受的事实：&#8220;Borland C++ Builder 6的高手<br>几乎都是Delphi高手&#8221;。</p>
<p>　　3.4 Borland C++ Builder X</p>
<p>　　正如前文所述，虽然版本号上和前面那个IDE非常相象，但是其实它们是完全不<br>同的两个集成开发环境。C++Builder更多的是一个和Delphi同步的C++版本的开发环<br>境，C++BuilderX则是完全从C++的角度思考得出的一个功能丰富的IDE。其最大的特<br>点是跨平台，跨编译器，多种Framework的集成，并且有一个WxWindows为基础的GU<br>I设计器。尤其是采用了纯C++来重写了整个Framework,摒弃了以前令人无奈的版本<br>。对于C++的开发来说，从编译器，到库，到功能集成都是非常理想的。可以预见，<br>Borland C++ Builder X 2.0很值得C++爱好者期待。唯一令人难堪之处是作为一个<br>C++的开发工具，其IDE是用Java写的，在配置不够理想的机器上请慎重考虑再安装<br>。</p>
<p>　　3.5 Emacs + GCC</p>
<p>　　前面讲的大部分是Windows环境下的集成开发环境。Linux上的开发者更倾向于<br>使用Emacs来编辑C++的文件，用Makefile来命令GCC做编译。虽然看上去比较松散，<br>但是这些东西综合起来还是一个开0发环境。如果你能够娴熟的使用这样的环境写程<br>序，你的水平应该足够指导我们来写这篇陋文了。</p>
<p>　　3.6 Dev C++</p>
<p>　　GCC是一个很好的编译器。在Windows上的C++编译器一直和标准有着一段距离的<br>时候，GCC就是一个让Windows下开发者流口水的编译器。Dev-C++就是能够让GCC跑<br>在Windows下的工具，作为集成开发环境，还提供了同专业IDE相媲美的语法高亮，<br>代码提示，调试等功能。由于使用Delphi开发，占用内存少，速度很快，比较适合<br>轻量级的学习和使用。</p>
<p>　　3.7 Eclipse + CDT</p>
<p>　　Eclipse可是近来大名鼎鼎的开发工具。最新一期的Jolt大奖就颁给了这个杰出<br>的神物。说其神奇是因为，它本身是用Java写的，但是拥有比一般Java写的程序快<br>得多的速度。而且因为其基于插件组装一切的原则，使得能够有CDT这样的插件把E<br>clipse变成一个C/C++的开发环境。如果你一直用Eclipse写Java的程序，不妨用它<br>体验一下C++开发的乐趣。</p>
<p>------------------------------------------------------------------------<br>--------</p>
<p>　　4，工具</p>
<p>　　C++的辅助工具繁多，我们分门别类的为大家作介绍：</p>
<p>　　4.1 文档类</p>
<p>　　(1) Doxygen</p>
<p>　　参考站点：<a href="http://www.doxygen.org/"><u><font color=#0000ff>http://www.doxygen.org</font></u></a></p>
<p>　　Doxygen是一种适合C风格语言（如C++、C、IDL、Java甚至包括C#和PHP）的、<br>开放源码的、基于命令行的文档产生器。</p>
<p>　　(2) C++2HTML</p>
<p>　　参考站点：<a href="http://www.bedaux.net/cpp2html/"><u><font color=#0000ff>http://www.bedaux.net/cpp2html/</font></u></a></p>
<p>　　把C++代码变成语法高亮的HTML</p>
<p>　　(3) CodeColorizer</p>
<p>　　参考站点：<a href="http://www.chami.com/colorizer/"><u><font color=#0000ff>http://www.chami.com/colorizer/</font></u></a></p>
<p>　　它能把好几种语言的源代码着色为HTML</p>
<p>　　(4) Doc-O-Matic</p>
<p>　　参考站点：<a href="http://www.doc-o-matic.com/"><u><font color=#0000ff>http://www.doc-o-matic.com/</font></u></a></p>
<p>　　Doc-O_Matic为你的C/C++，C++.net，Delphi/Pascal, VB.NET，C#和Java程序<br>或者组件产生准确的文档。Doc-O-Matic使用源代码中的符号和注释以及外部的文档<br>文件创建与流行的文档样式一致的文档。</p>
<p>　　(5) DocVizor</p>
<p>　　参考站点：<a href="http://www.ucancode.net/Products/DocBuilder/Features.htm"><u><font color=#0000ff>http://www.ucancode.net/Products/DocBuilder/Features.htm</font></u></a></p>
<p>　　DocVizor满足了面向对象软件开发者的基本要求——它让我们能够看到C++工程<br>中的类层次结构。DocVizor快速地产生完整可供打印的类层次结构图，包括从第三<br>方库中来的那些类，除此之外DocVizor还能从类信息中产生HTML文件。</p>
<p>　　(6) SourcePublisher C++</p>
<p>　　参考站点：<a href="http://www.scitools.com/sourcepublisher_c.html"><u><font color=#0000ff>http://www.scitools.com/sourcepublisher_c.html</font></u></a></p>
<p>　　给源代码产生提供快速直观的HTML报表，包括代码，类层次结构，调用和被调<br>用树，包含和被包含树。支持多种操作系统。</p>
<p>　　(7) Understand</p>
<p>　　参考站点：<a href="http://www.scitools.com/ucpp.html"><u><font color=#0000ff>http://www.scitools.com/ucpp.html</font></u></a></p>
<p>　　分析任何规模的C或者C++工程，帮助我们更好的理解以及编写文档。</p>
<p>　　4.2 代码类</p>
<p>　　(1) CC-Rider</p>
<p>　　参考站点：<a href="http://www.cc-rider.com/"><u><font color=#0000ff>http://www.cc-rider.com</font></u></a></p>
<p>　　CC-Rider是用于C/C++程序强大的代码可视化工具，通过交互式浏览、编辑及自<br>动文件来促进程序的维持和发展。</p>
<p>　　(2) CodeInspect</p>
<p>　　参考站点：<a href="http://www.yokasoft.com/"><u><font color=#0000ff>http://www.yokasoft.com/</font></u></a></p>
<p>　　一种新的C/C++代码分析工具。它检查我们的源代码找出非标准的，可能的，以<br>及普通的错误代码。</p>
<p>　　(3) CodeWizard</p>
<p>　　参考站点：<a href="http://www.parasoft.com/"><u><font color=#0000ff>http://www.parasoft.com</font></u></a></p>
<p>　　先进的C/C++源代码分析工具，使用超过500个编码规范自动化地标明危险的，<br>但是编译器不能检查到的代码结构。</p>
<p>　　(4) C++ Validation Test Suites</p>
<p>　　参考站点：<a href="http://www.plumhall.com/suites.html"><u><font color=#0000ff>http://www.plumhall.com/suites.html</font></u></a></p>
<p>　　一组用于测试编译器和库对于标准吻合程度的代码库。</p>
<p>　　(5) CppRefactory</p>
<p>　　参考站点：<a href="http://cpptool.sourceforge.net/"><u><font color=#0000ff>http://cpptool.sourceforge.net/</font></u></a></p>
<p>　　CPPRefactory是一个使得开发者能够重构他们的C++代码的程序。目的是使得C<br>++代码的重构能够尽可能的有效率和简单。</p>
<p>　　(6) Lzz</p>
<p>　　参考站点：<a href="http://www.lazycplusplus.com/"><u><font color=#0000ff>http://www.lazycplusplus.com/</font></u></a></p>
<p>　　Lzz是一个自动化许多C++编程中的体力活的工具。它能够节省我们许多事件并<br>且使得编码更加有乐趣。给出一系列的声明，Lzz会给我们创建头文件和源文件。</p>
<p>　　(7) QA C++ Generation 2000</p>
<p>　　参考站点：<a href="http://www.programmingresearch.com/solutions/qacpp.htm"><u><font color=#0000ff>http://www.programmingresearch.com/solutions/qacpp.htm</font></u></a></p>
<p>　　它关注面向对象的C++源代码，对有关于设计，效率，可靠性，可维护性的部分<br>提出警告信息。</p>
<p>　　(8) s-mail project - Java to C++DOL</p>
<p>　　参考站点：<a href="http://sadlocha.strefa.pl/s-mail/ja2dol.html"><u><font color=#0000ff>http://sadlocha.strefa.pl/s-mail/ja2dol.html</font></u></a></p>
<p>　　把Java源代码翻译为相应的C++源代码的命令行工具。</p>
<p>　　(9) SNIP from Cleanscape Software International</p>
<p>　　参考站点：<a href="http://www.cleanscape.net/stdprod/snip/index.html"><u><font color=#0000ff>http://www.cleanscape.net/stdprod/snip/index.html</font></u></a></p>
<p>　　一个填平编码和设计之间沟壑的易于使用的C++开发工具，节省大量编辑和调试<br>的事件，它还使得开发者能够指定设计模式作为对象模型，自动从对象模型中产生<br>C++的类。</p>
<p>　　(10) SourceStyler C++</p>
<p>　　参考站点：<a href="http://www.ochresoftware.com/"><u><font color=#0000ff>http://www.ochresoftware.com/</font></u></a></p>
<p>　　对C/C++源代码提供完整的格式化和排版控制的工具。提供多于75个的格式化选<br>项以及完全支持ANSI C++。</p>
<p>　　4.3 编译类</p>
<p>　　(1) Compilercache</p>
<p>　　参考站点：<a href="http://www.erikyyy.de/compilercache/"><u><font color=#0000ff>http://www.erikyyy.de/compilercache/</font></u></a></p>
<p>　　Compilercache是一个对你的C和C++编译器的封装脚本。每次我们进行编译，封<br>装脚本，把编译的结果放入缓存，一旦编译相同的东西，结果将从缓存中取出而不<br>是再次编译。</p>
<p>　　(2) Ccache</p>
<p>　　参考站点：<a href="http://ccache.samba.org/"><u><font color=#0000ff>http://ccache.samba.org/</font></u></a></p>
<p>　　Ccache是一个编译器缓存。它使用起来就像C/C++编译器的缓存预处理器，编译<br>速度通常能提高普通编译过程的5~10倍。</p>
<p>　　(3) Cmm (C++ with MultiMethods)</p>
<p>　　参考站点：<a href="http://www.op59.net/cmm/cmm-0.28/users.html"><u><font color=#0000ff>http://www.op59.net/cmm/cmm-0.28/users.html</font></u></a></p>
<p>　　这是一种C++语言的扩展。读入Cmm源代码输出C++的源代码，功能是对C++语言<br>添加了对multimethod的支持。</p>
<p>　　(4) The Frost Project</p>
<p>　　参考站点：<a href="http://frost.flewid.de/"><u><font color=#0000ff>http://frost.flewid.de/</font></u></a></p>
<p>　　Forst使得你能够在C++程序中像原生的C++特性一样使用multimethod以及虚函<br>数参数。它是一个编译器的外壳。</p>
<p>　　4.4 测试和调试类</p>
<p>　　(1) CPPUnit</p>
<p>　　CppUnit 是个基于 LGPL 的开源项目，最初版本移植自 JUnit，是一个非常优<br>秀的开源测试框架。CppUnit 和 JUnit 一样主要思想来源于极限编程。主要功能就<br>是对单元测试进行管理，并可进行自动化测试。</p>
<p>　　(2) C++Test</p>
<p>　　参考站点：<a href="http://www.parasoft.com/"><u><font color=#0000ff>http://www.parasoft.com/</font></u></a></p>
<p>　　C++ Test是一个单元测试工具，它自动化了C和C++类，函数或者组件的测试。</p>
<p><br>　　(3) Cantata++</p>
<p>　　参考站点：<a href="http://www.iplbath.com/products/tools/pt400.shtml"><u><font color=#0000ff>http://www.iplbath.com/products/tools/pt400.shtml</font></u></a></p>
<p>　　设计的目的是为了满足在合理的经济开销下使用这个工具可以让开发工程师开<br>展单元测试和集成测试的需求.</p>
<p>　　(4) Purify</p>
<p>　　参考站点：<a href="http://www-900.ibm.com/cn/software/rational/products/purif"><u><font color=#0000ff>http://www-900.ibm.com/cn/software/rational/products/purif</font></u></a><br>yplus/index.shtml</p>
<p>　　IBM Rational PurifyPlus是一套完整的运行时分析工具，旨在提高应用程序的<br>可靠性和性能。PurifyPlus将内存错误和泄漏检测、应用程序性能描述、代码覆盖<br>分析等功能组合在一个单一、完整的工具包中。</p>
<p>　　(5) BoundsChecker</p>
<p>　　BoundsChecker是一个C++运行时错误检测和调试工具。它通过在Visual Studi<br>o内自动化调试过程加速开发并且缩短上市的周期。BoundsChecker提供清楚，详细<br>的程序错误分析，许多是对C++独有的并且在static，stack和heap内存中检测和诊<br>断错误，以及发现内存和资源的泄漏。　　(6) Insure++</p>
<p>　　参考站点：<a href="http://www.parasoft.com/"><u><font color=#0000ff>http://www.parasoft.com/</font></u></a></p>
<p>　　一个自动化的运行时程序测试工具，检查难以察觉的错误,如内存覆盖，内存泄<br>漏，内存分配错误，变量初始化错误，变量定义冲突，指针错误，库错误，逻辑错<br>误和算法错误等。</p>
<p>　　(7) GlowCode</p>
<p>　　参考站点：<a href="http://www.glowcode.com/"><u><font color=#0000ff>http://www.glowcode.com/</font></u></a></p>
<p>　　GlowCode包括内存泄漏检查，code profiler，函数调用跟踪等功能。给C++开<br>发者提供完整的错误诊断，和运行时性能分析工具包。</p>
<p>　　(8) Stack Spy</p>
<p>　　参考站点：<a href="http://www.imperioustech.com/"><u><font color=#0000ff>http://www.imperioustech.com/</font></u></a></p>
<p>　　它能捕捉stack corruption, stack over run, stack overflow等有关栈的错<br>误。</p>
<p>------------------------------------------------------------------------<br>--------</p>
<p>　　5，库</p>
<p>　　在C++中，库的地位是非常高的。C++之父 Bjarne Stroustrup先生多次表示了<br>设计库来扩充功能要好过设计更多的语法的言论。现实中，C++的库门类繁多，解决<br>的问题也是极其广泛，库从轻量级到重量级的都有。不少都是让人眼界大开，亦或<br>是望而生叹的思维杰作。由于库的数量非常庞大，而且限于笔者水平，其中很多并<br>不了解。所以文中所提的一些库都是比较著名的大型库。</p>
<p>　　5.1 标准库</p>
<p>　　标准库中提供了C++程序的基本设施。虽然C++标准库随着C++标准折腾了许多年<br>，直到标准的出台才正式定型，但是在标准库的实现上却很令人欣慰得看到多种实<br>现，并且已被实践证明为有工业级别强度的佳作。</p>
<p>　　(1) Dinkumware C++ Library</p>
<p>　　参考站点：<a href="http://www.dinkumware.com/"><u><font color=#0000ff>http://www.dinkumware.com/</font></u></a></p>
<p>　　P.J. Plauger编写的高品质的标准库。P.J. Plauger博士是Dr. Dobb's程序设<br>计杰出奖的获得者。其编写的库长期被Microsoft采用，并且最近Borland也取得了<br>其OEM的license，在其C/C++的产品中采用Dinkumware的库。</p>
<p>　　(2) RogueWave Standard C++ Library</p>
<p>　　参考站点：<a href="http://www.roguewave.com/"><u><font color=#0000ff>http://www.roguewave.com/</font></u></a></p>
<p>　　这个库在Borland C++ Builder的早期版本中曾经被采用，后来被其他的库给替<br>换了。笔者不推荐使用。</p>
<p>　　(3) SGI STL</p>
<p>　　参考站点：<a href="http://www.roguewave.com/"><u><font color=#0000ff>http://www.roguewave.com/</font></u></a></p>
<p>　　SGI公司的C++标准模版库。</p>
<p>　　(4) STLport</p>
<p>　　参考站点：<a href="http://www.stlport.org/"><u><font color=#0000ff>http://www.stlport.org/</font></u></a></p>
<p>　　SGI STL库的跨平台可移植版本。</p>
<p>　　5.2 &#8220;准&#8221;标准库 - Boost</p>
<p>　　参考站点：<a href="http://www.boost.org/"><u><font color=#0000ff>http://www.boost.org</font></u></a></p>
<p>　　国内镜像：<a href="http://www.c-view.org/tech/lib/boost/index.htm"><u><font color=#0000ff>http://www.c-view.org/tech/lib/boost/index.htm</font></u></a></p>
<p>　　Boost库是一个经过千锤百炼、可移植、提供源代码的C++库，作为标准库的后<br>备，是C++标准化进程的发动机之一。 Boost库由C++标准委员会库工作组成员发起<br>，在C++社区中影响甚大，其成员已近2000人。 Boost库为我们带来了最新、最酷、<br>最实用的技术，是不折不扣的&#8220;准&#8221;标准库。</p>
<p>　　Boost中比较有名气的有这么几个库：</p>
<p>　　Regex</p>
<p>　　正则表达式库</p>
<p>　　Spirit</p>
<p>　　LL parser framework，用C++代码直接表达EBNF</p>
<p>　　Graph</p>
<p>　　图组件和算法</p>
<p>　　Lambda</p>
<p>　　在调用的地方定义短小匿名的函数对象，很实用的functional功能</p>
<p>　　concept check</p>
<p>　　检查泛型编程中的concept</p>
<p>&nbsp;</p>
<p>　　Mpl</p>
<p>　　用模板实现的元编程框架</p>
<p>&nbsp;</p>
<p>　　Thread</p>
<p>　　可移植的C++多线程库</p>
<p>&nbsp;</p>
<p>　　Python</p>
<p>　　把C++类和函数映射到Python之中</p>
<p>　　Pool</p>
<p>　　内存池管理</p>
<p>&nbsp;</p>
<p>　　smart_ptr</p>
<p>　　5个智能指针，学习智能指针必读，一份不错的参考是来自CUJ的文章：</p>
<p>　　Smart Pointers in Boost，哦，这篇文章可以查到，CUJ是提供在线浏览的。<br>中文版见笔者在《Dr. Dobb's Journal软件研发杂志》第7辑上的译文。</p>
<p>　　Boost总体来说是实用价值很高，质量很高的库。并且由于其对跨平台的强调，<br>对标准C++的强调，是编写平台无关，现代C++的开发者必备的工具。但是Boost中也<br>有很多是实验性质的东西，在实际的开发中实用需要谨慎。并且很多Boost中的库功<br>能堪称对语言功能的扩展，其构造用尽精巧的手法，不要贸然的花费时间研读。Bo<br>ost另外一面，比如Graph这样的库则是具有工业强度，结构良好，非常值得研读的<br>精品代码，并且也可以放心的在产品代码中多多利用。</p>
<p>　　5.3 GUI</p>
<p>　　在众多C++的库中，GUI部分的库算是比较繁荣，也比较引人注目的。在实际开<br>发中，GUI库的选择也是非常重要的一件事情，下面我们综述一下可选择的GUI库，<br>各自的特点以及相关工具的支持。</p>
<p>　　(1) MFC</p>
<p>　　大名鼎鼎的微软基础类库（Microsoft Foundation Class）。大凡学过VC++的<br>人都应该知道这个库。虽然从技术角度讲，MFC是不大漂亮的，但是它构建于Windo<br>ws API 之上，能够使程序员的工作更容易,编程效率高，减少了大量在建立 Windo<br>ws 程序时必须编写的代码，同时它还提供了所有一般 C++ 编程的优点，例如继承<br>和封装。MFC 编写的程序在各个版本的Windows操作系统上是可移植的，例如，在<br>Windows 3.1下编写的代码可以很容易地移植到 Windows NT 或 Windows 95 上。但<br>是在最近发展以及官方支持上日渐势微。</p>
<p>　　(2) QT</p>
<p>　　参考网站：<a href="http://www.trolltech.com/"><u><font color=#0000ff>http://www.trolltech.com/</font></u></a></p>
<p>　　Qt是Trolltech公司的一个多平台的C++图形用户界面应用程序框架。它提供给<br>应用程序开发者建立艺术级的图形用户界面所需的所用功能。Qt是完全面向对象的<br>很容易扩展，并且允许真正地组件编程。自从1996年早些时候，Qt进入商业领域，<br>它已经成为全世界范围内数千种成功的应用程序的基础。Qt也是流行的Linux桌面环<br>境KDE 的基础，同时它还支持Windows、Macintosh、Unix/X11等多种平台。</p>
<p>　　(3) WxWindows</p>
<p>　　参考网站：<a href="http://www.wxwindows.org/"><u><font color=#0000ff>http://www.wxwindows.org/</font></u></a></p>
<p>　　跨平台的GUI库。因为其类层次极像MFC，所以有文章介绍从MFC到WxWindows的<br>代码移植以实现跨平台的功能。通过多年的开发也是一个日趋完善的GUI库，支持同<br>样不弱于前面两个库。并且是完全开放源代码的。新近的C++ Builder X的GUI设计<br>器就是基于这个库的。</p>
<p>　　(4) Fox</p>
<p>　　参考网站：<a href="http://www.fox-toolkit.org/"><u><font color=#0000ff>http://www.fox-toolkit.org/</font></u></a></p>
<p>　　开放源代码的GUI库。作者从自己亲身的开发经验中得出了一个理想的GUI库应<br>该是什么样子的感受出发，从而开始了对这个库的开发。有兴趣的可以尝试一下。</p>
<p><br>　　(5) WTL</p>
<p>　　基于ATL的一个库。因为使用了大量ATL的轻量级手法，模板等技术，在代码尺<br>寸，以及速度优化方面做得非常到位。主要面向的使用群体是开发COM轻量级供网络<br>下载的可视化控件的开发者。</p>
<p>　　(6) GTK</p>
<p>　　参考网站：<a href="http://gtkmm.sourceforge.net/"><u><font color=#0000ff>http://gtkmm.sourceforge.net/</font></u></a></p>
<p>　　GTK是一个大名鼎鼎的C的开源GUI库。在Linux世界中有Gnome这样的杀手应用。<br>而GTK就是这个库的C++封装版本。</p>
<p>　　5.4 网络通信</p>
<p>　　(1) ACE</p>
<p>　　参考网站：<a href="http://www.cs.wustl.edu/~schmidt/ACE.html"><u><font color=#0000ff>http://www.cs.wustl.edu/~schmidt/ACE.html</font></u></a></p>
<p>　　C++库的代表，超重量级的网络通信开发框架。ACE自适配通信环境（Adaptive<br>&nbsp;Communication Environment）是可以自由使用、开放源代码的面向对象框架，在<br>其中实现了许多用于并发通信软件的核心模式。ACE提供了一组丰富的可复用C++包<br>装外观（Wrapper Facade）和框架组件，可跨越多种平台完成通用的通信软件任务<br>，其中包括：事件多路分离和事件处理器分派、信号处理、服务初始化、进程间通<br>信、共享内存管理、消息路由、分布式服务动态（重）配置、并发执行和同步，等<br>等。</p>
<p>　　(2) StreamModule</p>
<p>　　参考网站：<a href="http://www.omnifarious.org/StrMod/"><u><font color=#0000ff>http://www.omnifarious.org/StrMod/</font></u></a></p>
<p>　　设计用于简化编写分布式程序的库。尝试着使得编写处理异步行为的程序更容<br>易，而不是用同步的外壳包起异步的本质。</p>
<p>　　(3) SimpleSocket</p>
<p>　　参考网站：<a href="http://home.hetnet.nl/~lcbokkers/simsock.htm"><u><font color=#0000ff>http://home.hetnet.nl/~lcbokkers/simsock.htm</font></u></a></p>
<p>　　这个类库让编写基于socket的客户/服务器程序更加容易。</p>
<p>　　(4) A Stream Socket API for C++</p>
<p>　　参考网站：<a href="http://www.pcs.cnu.edu/~dgame/sockets/socketsC++/sockets.h"><u><font color=#0000ff>http://www.pcs.cnu.edu/~dgame/sockets/socketsC++/sockets.h</font></u></a><br>tml</p>
<p>　　又一个对Socket的封装库。</p>
<p>　　5.5 XML</p>
<p>　　(1) Xerces</p>
<p>　　参考网站：<a href="http://xml.apache.org/xerces-c/"><u><font color=#0000ff>http://xml.apache.org/xerces-c/</font></u></a></p>
<p>　　Xerces-C++ 是一个非常健壮的XML解析器，它提供了验证，以及SAX和DOM API<br>。XML验证在文档类型定义(Document Type Definition，DTD)方面有很好的支持，<br>并且在2001年12月增加了支持W3C XML Schema 的基本完整的开放标准。</p>
<p>　　(2) XMLBooster</p>
<p>　　参考网站：<a href="http://www.xmlbooster.com/"><u><font color=#0000ff>http://www.xmlbooster.com/</font></u></a></p>
<p>　　这个库通过产生特制的parser的办法极大的提高了XML解析的速度，并且能够产<br>生相应的GUI程序来修改这个parser。在DOM和SAX两大主流XML解析办法之外提供了<br>另外一个可行的解决方案。</p>
<p>　　(3) Pull Parser</p>
<p>　　参考网站：<a href="http://www.extreme.indiana.edu/xgws/xsoap/xpp/"><u><font color=#0000ff>http://www.extreme.indiana.edu/xgws/xsoap/xpp/</font></u></a></p>
<p>　　这个库采用pull方法的parser。在每个SAX的parser底层都有一个pull的parse<br>r，这个xpp把这层暴露出来直接给大家使用。在要充分考虑速度的时候值得尝试。</p>
<p><br>　　(4) Xalan</p>
<p>　　参考网站：<a href="http://xml.apache.org/xalan-c/"><u><font color=#0000ff>http://xml.apache.org/xalan-c/</font></u></a></p>
<p>　　Xalan是一个用于把XML文档转换为HTML，纯文本或者其他XML类型文档的XSLT处<br>理器。</p>
<p>　　(5) CMarkup</p>
<p>　　参考网站：<a href="http://www.firstobject.com/xml.htm"><u><font color=#0000ff>http://www.firstobject.com/xml.htm</font></u></a></p>
<p>　　这是一种使用EDOM的XML解析器。在很多思路上面非常灵活实用。值得大家在D<br>OM和SAX之外寻求一点灵感。</p>
<p>　　(6) libxml++</p>
<p>　　<a href="http://libxmlplusplus.sourceforge.net/"><u><font color=#0000ff>http://libxmlplusplus.sourceforge.net/</font></u></a></p>
<p>　　libxml++是对著名的libxml XML解析器的C++封装版本</p>
<p>　　5.6 科学计算</p>
<p>　　(1) Blitz++</p>
<p>　　参考网站：<a href="http://www.oonumerics.org/blitz/"><u><font color=#0000ff>http://www.oonumerics.org/blitz/</font></u></a></p>
<p>　　Blitz++ 是一个高效率的数值计算函数库，它的设计目的是希望建立一套既具<br>像C++ 一样方便，同时又比Fortran速度更快的数值计算环境。通常，用C++所写出<br>的数值程序，比 Fortran慢20%左右，因此Blitz++正是要改掉这个缺点。方法是利<br>用C++的template技术，程序执行甚至可以比Fortran更快。Blitz++目前仍在发展中<br>，对于常见的SVD，FFTs，QMRES等常见的线性代数方法并不提供，不过使用者可以<br>很容易地利用Blitz++所提供的函数来构建。</p>
<p>　　(2) POOMA</p>
<p>　　参考网站：<a href="http://www.codesourcery.com/pooma/pooma"><u><font color=#0000ff>http://www.codesourcery.com/pooma/pooma</font></u></a></p>
<p>　　POOMA是一个免费的高性能的C++库，用于处理并行式科学计算。POOMA的面向对<br>象设计方便了快速的程序开发，对并行机器进行了优化以达到最高的效率，方便在<br>工业和研究环境中使用。</p>
<p>　　(3) MTL</p>
<p>　　参考网站：<a href="http://www.osl.iu.edu/research/mtl/"><u><font color=#0000ff>http://www.osl.iu.edu/research/mtl/</font></u></a></p>
<p>　　Matrix Template Library(MTL)是一个高性能的泛型组件库，提供了各种格式<br>矩阵的大量线性代数方面的功能。在某些应用使用高性能编译器的情况下，比如In<br>tel的编译器，从产生的汇编代码可以看出其与手写几乎没有两样的效能。</p>
<p>　　(4) CGAL</p>
<p>　　参考网站：<a href="http://www.cgal.org/"><u><font color=#0000ff>www.cgal.org</font></u></a></p>
<p>　　Computational Geometry Algorithms Library的目的是把在计算几何方面的大<br>部分重要的解决方案和方法以C++库的形式提供给工业和学术界的用户。</p>
<p>　　5.7 游戏开发</p>
<p>　　(1) Audio/Video 3D C++ Programming Library</p>
<p>　　参考网站：<a href="http://www.galacticasoftware.com/products/av/"><u><font color=#0000ff>http://www.galacticasoftware.com/products/av/</font></u></a></p>
<p>　　***3D是一个跨平台，高性能的C++库。主要的特性是提供3D图形，声效支持（S<br>B,以及S3M），控制接口（键盘，鼠标和遥感），XMS。</p>
<p>　　(2) KlayGE</p>
<p>　　参考网站：<a href="http://home.g365.net/enginedev/"><u><font color=#0000ff>http://home.g365.net/enginedev/</font></u></a></p>
<p>　　国内游戏开发高手自己用C++开发的游戏引擎。KlayGE是一个开放源代码、跨平<br>台的游戏引擎，并使用Python作脚本语言。KlayGE在LGPL协议下发行。感谢龚敏敏<br>先生为中国游戏开发事业所做出的贡献。</p>
<p>　　(3) OGRE</p>
<p>　　参考网站：<a href="http://www.ogre3d.org/"><u><font color=#0000ff>http://www.ogre3d.org</font></u></a></p>
<p>　　OGRE（面向对象的图形渲染引擎）是用C++开发的，使用灵活的面向对象3D引擎<br>。它的目的是让开发者能更方便和直接地开发基于3D硬件设备的应用程序或游戏。<br>引擎中的类库对更底层的系统库（如：Direct3D和OpenGL）的全部使用细节进行了<br>抽象，并提供了基于现实世界对象的接口和其它类。</p>
<p>　　5.8 线程</p>
<p>　　(1) C++ Threads</p>
<p>　　参考网站：<a href="http://threads.sourceforge.net/"><u><font color=#0000ff>http://threads.sourceforge.net/</font></u></a></p>
<p>　　这个库的目标是给程序员提供易于使用的类，这些类被继承以提供在Linux环境<br>中很难看到的大量的线程方面的功能。</p>
<p>　　(2) ZThreads</p>
<p>　　参考网站：<a href="http://zthread.sourceforge.net/"><u><font color=#0000ff>http://zthread.sourceforge.net/</font></u></a></p>
<p>　　一个先进的面向对象，跨平台的C++线程和同步库。</p>
<p>　　5.9 序列化</p>
<p>　　(1) s11n</p>
<p>　　参考网站：<a href="http://s11n.net/"><u><font color=#0000ff>http://s11n.net/</font></u></a></p>
<p>　　一个基于STL的C++库，用于序列化POD，STL容器以及用户定义的类型。</p>
<p>　　(2) Simple XML Persistence Library</p>
<p>　　参考网站：<a href="http://sxp.sourceforge.net/"><u><font color=#0000ff>http://sxp.sourceforge.net/</font></u></a></p>
<p>　　这是一个把对象序列化为XML的轻量级的C++库。</p>
<p>　　5.10 字符串</p>
<p>　　(1) C++ Str Library</p>
<p>　　参考网站：<a href="http://www.utilitycode.com/str/"><u><font color=#0000ff>http://www.utilitycode.com/str/</font></u></a></p>
<p>　　操作字符串和字符的库，支持Windows和支持gcc的多种平台。提供高度优化的<br>代码，并且支持多线程环境和Unicode，同时还有正则表达式的支持。</p>
<p>　　(2) Common Text Transformation Library</p>
<p>　　参考网站：<a href="http://cttl.sourceforge.net/"><u><font color=#0000ff>http://cttl.sourceforge.net/</font></u></a></p>
<p>　　这是一个解析和修改STL字符串的库。CTTL substring类可以用来比较，插入，<br>替换以及用EBNF的语法进行解析。</p>
<p>　　(3) GRETA</p>
<p>　　参考网站：<a href="http://research.microsoft.com/projects/greta/"><u><font color=#0000ff>http://research.microsoft.com/projects/greta/</font></u></a></p>
<p>　　这是由微软研究院的研究人员开发的处理正则表达式的库。在小型匹配的情况<br>下有非常优秀的表现。</p>
<p>　　5.11 综合</p>
<p>　　(1) P::Classes</p>
<p>　　参考网站：<a href="http://pclasses.com/"><u><font color=#0000ff>http://pclasses.com/</font></u></a></p>
<p>　　一个高度可移植的C++应用程序框架。当前关注类型和线程安全的signal/slot<br>机制，i/o系统包括基于插件的网络协议透明的i/o架构，基于插件的应用程序消息<br>日志框架，访问sql数据库的类等等。</p>
<p>　　(2) ACDK - Artefaktur Component Development Kit</p>
<p>　　参考网站：<a href="http://acdk.sourceforge.net/"><u><font color=#0000ff>http://acdk.sourceforge.net/</font></u></a></p>
<p>　　这是一个平台无关的C++组件框架，类似于Java或者.NET中的框架（反射机制，<br>线程，Unicode，废料收集，I/O，网络，实用工具，XML，等等），以及对Java, P<br>erl, Python, TCL, Lisp, COM 和 CORBA的集成。</p>
<p>　　(3) dlib C++ library</p>
<p>　　参考网站：<a href="http://www.cis.ohio-state.edu/~kingd/dlib/"><u><font color=#0000ff>http://www.cis.ohio-state.edu/~kingd/dlib/</font></u></a></p>
<p>　　各种各样的类的一个综合。大整数，Socket，线程，GUI，容器类,以及浏览目<br>录的API等等。</p>
<p>　　(4) Chilkat C++ Libraries</p>
<p>　　参考网站：<a href="http://www.chilkatsoft.com/cpp_libraries.asp"><u><font color=#0000ff>http://www.chilkatsoft.com/cpp_libraries.asp</font></u></a></p>
<p>　　这是提供zip，e-mail，编码，S/MIME，XML等方面的库。</p>
<p>　　(5) C++ Portable Types Library (PTypes)</p>
<p>　　参考网站：<a href="http://www.melikyan.com/ptypes/"><u><font color=#0000ff>http://www.melikyan.com/ptypes/</font></u></a></p>
<p>　　这是STL的比较简单的替代品，以及可移植的多线程和网络库。</p>
<p>　　(6) LFC</p>
<p>　　参考网站：<a href="http://lfc.sourceforge.net/"><u><font color=#0000ff>http://lfc.sourceforge.net/</font></u></a></p>
<p>　　哦，这又是一个尝试提供一切的C++库</p>
<p>　　5.12 其他库</p>
<p>　　(1) Loki</p>
<p>　　参考网站：<a href="http://www.moderncppdesign.com/"><u><font color=#0000ff>http://www.moderncppdesign.com/</font></u></a></p>
<p>　　哦，你可能抱怨我早该和Boost一起介绍它，一个实验性质的库。作者在loki中<br>把C++模板的功能发挥到了极致。并且尝试把类似设计模式这样思想层面的东西通过<br>库来提供。同时还提供了智能指针这样比较实用的功能。</p>
<p>　　(2) ATL</p>
<p>　　ATL(Active Template Library)</p>
<p>　　是一组小巧、高效、灵活的类，这些类为创建可互操作的COM组件提供了基本的<br>设施。</p>
<p>　　(3) FC++: The Functional C++ Library</p>
<p>　　这个库提供了一些函数式语言中才有的要素。属于用库来扩充语言的一个代表<br>作。如果想要在OOP之外寻找另一分的乐趣，可以去看看函数式程序设计的世界。大<br>师Peter Norvig在 &#8220;Teach Yourself Programming in Ten Years&#8221;一文中就将函<br>数式语言列为至少应当学习的6类编程语言之一。</p>
<p>　　(4) FACT!</p>
<p>　　参考网站：<a href="http://www.kfa-juelich.de/zam/FACT/start/index.html"><u><font color=#0000ff>http://www.kfa-juelich.de/zam/FACT/start/index.html</font></u></a></p>
<p>　　另外一个实现函数式语言特性的库</p>
<p>　　(5) Crypto++</p>
<p>　　提供处理密码，消息验证，单向hash，公匙加密系统等功能的免费库。</p>
<p>　　还有很多非常激动人心或者是极其实用的C++库，限于我们的水平以及文章的篇<br>幅不能包括进来。在对于这些已经包含近来的库的介绍中，由于并不是每一个我们<br>都使用过，所以难免有偏颇之处，请读者见谅。</p>
<p>------------------------------------------------------------------------<br>--------</p>
<p>　　6，书籍</p>
<p>　　以前熊节先生曾撰文评论相对于Java程序设计语言，C++的好书多如牛毛。荣耀<br>先生在《程序员》杂志上撰文《C++程序设计之四书五经》也将本领域内几乎所有的<br>经典书籍作了全面的介绍,任何关于书的评论此时看来便是很多余的了。个人浅见，<br>除非你打算以C++作为唯一兴趣或者生存之本，一般读者确实没有足够的时间和必要<br>将20余本书籍全部阅读。更有参考价值的是荣耀先生的另一篇文章：《至少应该阅<br>读的九本C++著作》，可以从下面的地址浏览到此文：</p>
<p>　　<a href="http://www.royaloo.com/articles/articles_2003/9CppBooks.htm"><u><font color=#0000ff>http://www.royaloo.com/articles/articles_2003/9CppBooks.htm</font></u></a></p>
<p>　　下面几本书对于走在C++初学之路上的读者是我们最愿意推荐给大家的：</p>
<p>　　(1) 《C++ Primer》</p>
<p>　　哦，也许你会抱怨我们为什么不先介绍TCPL,但对于走在学习之路上的入门者，<br>本书内容更为全面，更为详细易懂，我们称它为&#8220;C++的超级宝典&#8221;并不过分。配有<br>一本不错的习题解答《C++ Primer Answer Book》可以辅助你的学习之路。</p>
<p>　　(2) 《Essential C++》</p>
<p>　　如果说《C++ Primer》是C++领域的超级宝典，那么此书作为掌握C++的大局观<br>当之无愧。正如《.NET大局观》一书能够让读者全揽.NET，本书讲述了C++中最核心<br>的全部主题。书虽不厚，内容精炼，不失为《C++ Primer》读者茶余饭后的主题回<br>顾之作。</p>
<p>　　(3) 《The C++ Programming Language》</p>
<p>　　Bjarne为你带来的C++教程，真正能够告诉你怎么用才叫真正的C++的唯一一本<br>书。虽然如同&#8220;某某程序设计语言&#8221;这样的书籍会给大家一个内容全揽，入门到精<br>通的感觉，但本书确实不太适合初学者阅读。如果你自认为是一名很有经验的C++程<br>序员，那至少也要反复咀嚼Bjarne先生所强调的若干内容。</p>
<p>　　(4) 《Effective C++》，《More Effective C++》</p>
<p>　　是的，正如一些C++爱好者经常以读过与没有读过上述两本作品来区分你是否是<br>C++高手。我们也极力推崇这两本著作。在各种介绍C++专家经验的书籍里面，这两<br>本是最贴近语言本质，看后最能够有脱胎换骨感觉的书，读此书你需每日三省汝身<br>。</p>
<p>　　技术书籍仁者见仁，过多的评论反无太多意义，由读者喜好选择最适合自己的<br>书方为上策。</p>
<p>------------------------------------------------------------------------<br>--------</p>
<p>　　7，资源网站</p>
<p>　　正如我们可以通过计算机历史上的重要人物了解计算机史的发展，C++相关人物<br>的网站也可以使我们得到最有价值的参考与借鉴，下面的人物我们认为没有介绍的<br>必要，只因下面的人物在C++领域的地位众所周知，我们只将相关的资源进行罗列以<br>供读者学习，他们有的工作于贝尔实验室，有的工作于知名编译器厂商，有的在不<br>断推进语言的标准化，有的为读者撰写了多部千古奇作&#8230;&#8230;<br>　　(1) Bjarne Stroustrup<br>　　<a href="http://www.research.att.com/~bs/"><u><font color=#0000ff>http://www.research.att.com/~bs/</font></u></a></p>
<p>　　(2) Stanley B. Lippman<br>　　<a href="http://blogs.msdn.com/slippman/"><u><font color=#0000ff>http://blogs.msdn.com/slippman/</font></u></a><br>　　中文版 <a href="http://www.zengyihome.net/slippman/index.htm"><u><font color=#0000ff>http://www.zengyihome.net/slippman/index.htm</font></u></a></p>
<p>　　(3) Scott Meyers<br>　　<a href="http://www.aristeia.com/"><u><font color=#0000ff>http://www.aristeia.com/</font></u></a></p>
<p>　　(4) David Musser<br>　　<a href="http://www.cs.rpi.edu/~musser/"><u><font color=#0000ff>http://www.cs.rpi.edu/~musser/</font></u></a></p>
<p>　　(5) Bruce Eckel<br>　　<a href="http://www.bruceeckel.com/"><u><font color=#0000ff>http://www.bruceeckel.com</font></u></a></p>
<p>　　(6) Nicolai M. Josuttis<br>　　<a href="http://www.josuttis.com/"><u><font color=#0000ff>http://www.josuttis.com/</font></u></a></p>
<p>　　(7) Herb Sutter<br>　　<a href="http://www.gotw.ca/"><u><font color=#0000ff>http://www.gotw.ca/</font></u></a></p>
<p>　　(8) Andrei Alexandrescu<br>　　<a href="http://www.coderncppdesign.com/"><u><font color=#0000ff>http://www.coderncppdesign.com/</font></u></a></p>
<p>　　(9) 侯捷先生<br>　　<a href="http://www.jjhou.com/"><u><font color=#0000ff>http://www.jjhou.com</font></u></a></p>
<p>　　(10) 孟岩先生<br>　　先生繁忙于工作，痴迷于技术，暂无个人主页，关于先生的作品可以通过CSDN<br>的专栏和侯先生的主页访问到。</p>
<p>　　(11) 荣耀先生<br>　　<a href="http://www.royaloo.com/"><u><font color=#0000ff>http://www.royaloo.com/</font></u></a></p>
<p>　　(12) 潘爱民先生<br>　　<a href="http://www.icst.pku.edu.cn/panaimin/pam_homepage.htm"><u><font color=#0000ff>http://www.icst.pku.edu.cn/panaimin/pam_homepage.htm</font></u></a></p>
<p>　　除了上述大师的主页外，以下的综合类C++学习参考站点是我们非常愿意向大家<br>推荐的：</p>
<p>　　(1) CodeProject<br>　　<a href="http://www.codeproject.com/"><u><font color=#0000ff>http://www.codeproject.com</font></u></a></p>
<p>　　(2) CodeGuru<br>　　<a href="http://www.codeguru.com/"><u><font color=#0000ff>http://www.codeguru.com</font></u></a></p>
<p>　　(3) Dr. Dobb's Journal<br>　　<a href="http://www.ddj.com/"><u><font color=#0000ff>http://www.ddj.com</font></u></a></p>
<p>　　(4) C/C++ Users Journal<br>　　<a href="http://www.cuj.com/"><u><font color=#0000ff>http://www.cuj.com</font></u></a></p>
<p>　　(5) C维视点<br>　　<a href="http://www.c-view.org/"><u><font color=#0000ff>http://www.c-view.org</font></u></a></p>
<p>　　(6) allaboutprogram<br>　　<a href="http://www.allaboutprogram.com/"><u><font color=#0000ff>http://www.allaboutprogram.com</font></u></a><br>　　其他资料</p>
<p>　　(1) ISO IEC JTC1/SC22/WG21 - C++：标准C++的权威参考<br>　　<a href="http://anubis.dkuug.dk/jtc1/sc22/wg21/"><u><font color=#0000ff>http://anubis.dkuug.dk/jtc1/sc22/wg21/</font></u></a></p>
<p>　　(2) C++ FAQ LITE — Frequently Asked Questions: 最为全面的C++FAQ<br>　　<a href="http://www.sunistudio.com/cppfaq/index.html"><u><font color=#0000ff>http://www.sunistudio.com/cppfaq/index.html</font></u></a><br>　　C/C++ 新闻组：<br>　　你不妨尝试从这里提问和回答问题，很多不错的Q&amp;A资源......</p>
<p>　　(1) .alt.comp.lang.learn.c-c++<br>　　这个简单些，如果你和我一样是个菜鸟</p>
<p>　　(2) .comp.lang.c++.moderated<br>&nbsp;&nbsp;&nbsp; 嗯，这个显然水平高一些</p>
<p>　　(3) .comp.std.c++<br>　　如果你需要讨论标准C++相关话题的话</p>
<p>------------------------------------------------------------------------<br>--------</p>
<p>　　8，不得不写的结束语</p>
<p>　　结束的时候也是总结现状，展望未来的时候。虽然C++从脱胎于C开始，一路艰<br>难坎坷的走过来，但是无论如何C++已经取得了工业基础的地位。文章列举的大量相关<br>资源就是最好的证明，而业界的大量用C++写成的产品代码以及大量的C++职业工程<br>师则是最直接的证明。同时，我们可以看到各个高校的计算机专业都开设有C++这门<br>课程，网络上对于C++的学习讨论也从来都没有停过。但是，在Java和.NET两大企业<br>开发平台的围攻下，给人的感觉是C++越来越&#8220;不行&#8221;了。</p>
<p>　　C++在面向企业的软件开发中，在开发便捷性等方面的确要比Java和C#差很多，<br>其中一个问题是C++语言本身比较复杂，学习曲线比较陡峭，另外一个问题是C++标<br>准化的时间太长，丧失了很多的壮大机会，耗费了很多精力在厂商的之间的斗争上<br>，而C++的标准库离一个完善的程序开发框架还缺少太多太多的内容，各个第三方的<br>类库和框架又在一致性和完整性上没法和随平台提供的框架相提并论。难道C++真的<br>要退出历史舞台了？</p>
<p>　　从C++目前的活跃程度，以及应用现状来说是完全能够肯定C++仍然是软件工业<br>的基础，也不会退出历史舞台的。另外从Boost，Loki这些库中我们也能够看到C++<br>的发展非常活跃，对于新技术新思维非常激进，C++仍然广泛受到关注。从ACE在高<br>性能通信领域的应用，以及MTL这样的库在数值计算领域的出色表现，我们可以看到<br>C++在高性能应用场合下的不可替代的作用，而嵌入式系统这样的内存受限开发平台<br>，比如Symbian OS上，C++已经发挥着并且将发挥更大的作用。可以预见的是以后的<br>软件无论上层的应用怎么变，它的底层核心都会是由C/C++这样的系统级软件编写的<br>，比如Java虚拟机，.NET Framwork。因为只有这样的系统级软件才能完全彻底的发<br>挥机器的功能。</p>
<p>　　需要看到的是两个趋势，一个趋势是C++变得更加复杂，更加学院派，通过模板<br>等有潜力的语法因素构造越来越精巧的库成为了现代C++的热点，虽然在利用库实现<br>新的编程范式，乃至设计模式等方面很有开创意义，也确实产生了一些能够便捷开<br>发的工具，但是更多的是把C++变得更加强大，更加复杂，也更加难懂，似乎也更加<br>学院派，不得不说它正在向边缘化道路发展。另一个趋势是C++在主流的企业应用开<br>发中已经逐渐退出了，ERP这样的企业软件开发中基本上不会考虑C++，除非需要考<br>虑性能或者和遗留代码的集成这些因素。C++退守到系统级别语言，成为软件工业的<br>基础是大势所趋。然而反思一下，真的是退守么？自从STL出现，无数的人风起云涌<br>的开始支持C++,他们狂呼&#8220;我看到深夜消失了，目标软件工程的出现。我看到了可<br>维护的代码。&#8221;是的，STL在可维护性下做得如此出色。但是又怎样呢？STL为C++铺<br>平了现代软件工程的道路，而在上层应用程序软件开发领域这块场地早不单独属于<br>C++,很多程序设计语言都做得很出色，疯狂的支持者会毫不犹豫地说我们应当支持<br>C++,因为它是世界上最棒的语言。而坦率地说，你的腰杆真的那么硬么？也许只是<br>在逃避一些事实。C++是优秀的，这不可否认，STL的出现让C++一度走上了最辉煌的<br>时刻，然而现在看来&#8230;&#8230;我的一位恩师曾言：真正能够将STL应用得淋漓尽致的人很<br>保守地说国内也不超过200人，或许不加入STL能够使C++向着它应当发展的方向发展<br>的更好，而现在看来，C++也应当回首到真正属于他的那一片圣地上&#8230;&#8230;</p>
<img src ="http://www.cppblog.com/cloud/aggbug/24835.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cloud/" target="_blank">cloud</a> 2007-05-25 16:39 <a href="http://www.cppblog.com/cloud/archive/2007/05/25/24835.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>断言的使用环境</title><link>http://www.cppblog.com/cloud/archive/2007/03/13/19694.html</link><dc:creator>cloud</dc:creator><author>cloud</author><pubDate>Tue, 13 Mar 2007 02:16:00 GMT</pubDate><guid>http://www.cppblog.com/cloud/archive/2007/03/13/19694.html</guid><wfw:comment>http://www.cppblog.com/cloud/comments/19694.html</wfw:comment><comments>http://www.cppblog.com/cloud/archive/2007/03/13/19694.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cloud/comments/commentRss/19694.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cloud/services/trackbacks/19694.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">1.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">输入参数或输出参数的取值处于预期的范围内</span>
				<span lang="EN-US">.</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">2.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">子程序开始</span>
				<span lang="EN-US">(</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或者结束</span>
				<span lang="EN-US">)</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">执行时</span>
				<span lang="EN-US">, </span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件或流是处于打开</span>
				<span lang="EN-US">(</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或者关闭</span>
				<span lang="EN-US">)</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的状态</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">3.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">子程序开始</span>
				<span lang="EN-US">(</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或者结束</span>
				<span lang="EN-US">)</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">执行时</span>
				<span lang="EN-US">, </span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件或流的读写未知处于开头</span>
				<span lang="EN-US">(</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或结尾</span>
				<span lang="EN-US">)</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">处</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">4.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件或流已用只度</span>
				<span lang="EN-US">, </span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">只写或可读可写方式打开</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">5.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">仅用于输入的变量的值没有被子程序所修改</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">6.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">指针非空</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">7.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">传入子程序的数组或其他容器至少能容纳</span>
				<span lang="EN-US">X</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个数据元素</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">8.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表已初始化</span>
				<span lang="EN-US">,</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">存储着真实的数值</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">9.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">子程序开始</span>
				<span lang="EN-US">(</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或结束</span>
				<span lang="EN-US">)</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">执行时</span>
				<span lang="EN-US">,</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">某个容器是空的</span>
				<span lang="EN-US">(</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或者满的</span>
				<span lang="EN-US">)</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">10.<span style="FONT: 7pt 'Times New Roman'">   </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一个经过高度优化的复杂子程序的运算结果和相对缓慢但代码清晰的子程序的预算结果相一致<br /><br />以上这些只是一些基本假定.可以有更多的端来来说明的假定</span>
		</p>
<img src ="http://www.cppblog.com/cloud/aggbug/19694.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cloud/" target="_blank">cloud</a> 2007-03-13 10:16 <a href="http://www.cppblog.com/cloud/archive/2007/03/13/19694.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对使用虚拟函数的一点思考</title><link>http://www.cppblog.com/cloud/archive/2007/03/05/19214.html</link><dc:creator>cloud</dc:creator><author>cloud</author><pubDate>Mon, 05 Mar 2007 01:24:00 GMT</pubDate><guid>http://www.cppblog.com/cloud/archive/2007/03/05/19214.html</guid><wfw:comment>http://www.cppblog.com/cloud/comments/19214.html</wfw:comment><comments>http://www.cppblog.com/cloud/archive/2007/03/05/19214.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cloud/comments/commentRss/19214.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cloud/services/trackbacks/19214.html</trackback:ping><description><![CDATA[      将虚拟函数声明为非公用的,将共用函数声明为非虚拟的.如果基类是需要被继承的,则其虚拟函数一定要是虚拟的.<br />      这个观点和Template Method模式可以说是殊途同归.<br />      如果一个基类的虚拟函数被声明为private,则<font face="Tahoma">可以认为派生类可以覆盖该虚拟函数，也可以不覆盖。但是不可以调用该函数的实现.<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">class</span><span style="COLOR: #000000"> Base<br /><img id="Codehighlighter1_11_79_Open_Image" onclick="this.style.display='none'; Codehighlighter1_11_79_Open_Text.style.display='none'; Codehighlighter1_11_79_Closed_Image.style.display='inline'; Codehighlighter1_11_79_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_11_79_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_11_79_Closed_Text.style.display='none'; Codehighlighter1_11_79_Open_Image.style.display='inline'; Codehighlighter1_11_79_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_11_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_11_79_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_33_43_Open_Image" onclick="this.style.display='none'; Codehighlighter1_33_43_Open_Text.style.display='none'; Codehighlighter1_33_43_Closed_Image.style.display='inline'; Codehighlighter1_33_43_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_33_43_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_33_43_Closed_Text.style.display='none'; Codehighlighter1_33_43_Open_Image.style.display='inline'; Codehighlighter1_33_43_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> f()</span><span id="Codehighlighter1_33_43_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_33_43_Open_Text"><span style="COLOR: #000000">{ do_f(); }</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" />    </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> do_f();<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000">;</span></div><br />      如果一个基类的虚拟函数被声明为protected,则可以认为派生类需要覆盖该虚拟函数,而且得调用基类的虚拟函数的实现<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">class</span><span style="COLOR: #000000"> Base<br /><img id="Codehighlighter1_11_81_Open_Image" onclick="this.style.display='none'; Codehighlighter1_11_81_Open_Text.style.display='none'; Codehighlighter1_11_81_Closed_Image.style.display='inline'; Codehighlighter1_11_81_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_11_81_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_11_81_Closed_Text.style.display='none'; Codehighlighter1_11_81_Open_Image.style.display='inline'; Codehighlighter1_11_81_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_11_81_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_11_81_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_33_43_Open_Image" onclick="this.style.display='none'; Codehighlighter1_33_43_Open_Text.style.display='none'; Codehighlighter1_33_43_Closed_Image.style.display='inline'; Codehighlighter1_33_43_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_33_43_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_33_43_Closed_Text.style.display='none'; Codehighlighter1_33_43_Open_Image.style.display='inline'; Codehighlighter1_33_43_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> f()</span><span id="Codehighlighter1_33_43_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_33_43_Open_Text"><span style="COLOR: #000000">{ do_f(); }</span></span><span style="COLOR: #000000"><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 src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> do_f();<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"> Derive : </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> Base<br /><img id="Codehighlighter1_112_231_Open_Image" onclick="this.style.display='none'; Codehighlighter1_112_231_Open_Text.style.display='none'; Codehighlighter1_112_231_Closed_Image.style.display='inline'; Codehighlighter1_112_231_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_112_231_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_112_231_Closed_Text.style.display='none'; Codehighlighter1_112_231_Open_Image.style.display='inline'; Codehighlighter1_112_231_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_112_231_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_112_231_Open_Text"><span style="COLOR: #000000">{<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 src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> do_f()<br /><img id="Codehighlighter1_153_229_Open_Image" onclick="this.style.display='none'; Codehighlighter1_153_229_Open_Text.style.display='none'; Codehighlighter1_153_229_Closed_Image.style.display='inline'; Codehighlighter1_153_229_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_153_229_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_153_229_Closed_Text.style.display='none'; Codehighlighter1_153_229_Open_Image.style.display='inline'; Codehighlighter1_153_229_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span id="Codehighlighter1_153_229_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_229_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> do something</span><span style="COLOR: #008000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: #000000">        Base::do_f();<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> do something</span><span style="COLOR: #008000"><br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" /></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">;</span></div></font><img src ="http://www.cppblog.com/cloud/aggbug/19214.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cloud/" target="_blank">cloud</a> 2007-03-05 09:24 <a href="http://www.cppblog.com/cloud/archive/2007/03/05/19214.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>