﻿<?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++博客-christanxw的专栏-随笔分类-C++/STL</title><link>http://www.cppblog.com/christanxw/category/479.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 21 May 2008 14:29:50 GMT</lastBuildDate><pubDate>Wed, 21 May 2008 14:29:50 GMT</pubDate><ttl>60</ttl><item><title>在A*算法中使用二叉堆（译）</title><link>http://www.cppblog.com/christanxw/archive/2006/04/09/5205.html</link><dc:creator>christanxw</dc:creator><author>christanxw</author><pubDate>Sun, 09 Apr 2006 12:38:00 GMT</pubDate><guid>http://www.cppblog.com/christanxw/archive/2006/04/09/5205.html</guid><wfw:comment>http://www.cppblog.com/christanxw/comments/5205.html</wfw:comment><comments>http://www.cppblog.com/christanxw/archive/2006/04/09/5205.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/christanxw/comments/commentRss/5205.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/christanxw/services/trackbacks/5205.html</trackback:ping><description><![CDATA[
		<p>
				<a href="http://blog.csdn.net/christanxw/archive/2006/04/09/656484.aspx">
						<font size="4">http://blog.csdn.net/christanxw/archive/2006/04/09/656484.aspx</font>
				</a>
		</p>
<img src ="http://www.cppblog.com/christanxw/aggbug/5205.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/christanxw/" target="_blank">christanxw</a> 2006-04-09 20:38 <a href="http://www.cppblog.com/christanxw/archive/2006/04/09/5205.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>A* 寻路算法</title><link>http://www.cppblog.com/christanxw/archive/2006/04/07/5126.html</link><dc:creator>christanxw</dc:creator><author>christanxw</author><pubDate>Fri, 07 Apr 2006 01:51:00 GMT</pubDate><guid>http://www.cppblog.com/christanxw/archive/2006/04/07/5126.html</guid><wfw:comment>http://www.cppblog.com/christanxw/comments/5126.html</wfw:comment><comments>http://www.cppblog.com/christanxw/archive/2006/04/07/5126.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.cppblog.com/christanxw/comments/commentRss/5126.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/christanxw/services/trackbacks/5126.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 原文地址：										http://www.gamedev.net/reference/articles/article2003.asp																														概述								虽然掌握了				A*				算法的人认为它容易，但是对于初学者来说，				A*				算法还是很复杂的。...&nbsp;&nbsp;<a href='http://www.cppblog.com/christanxw/archive/2006/04/07/5126.html'>阅读全文</a><img src ="http://www.cppblog.com/christanxw/aggbug/5126.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/christanxw/" target="_blank">christanxw</a> 2006-04-07 09:51 <a href="http://www.cppblog.com/christanxw/archive/2006/04/07/5126.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何在编译时刻就可判断type T 是否包含member type X </title><link>http://www.cppblog.com/christanxw/archive/2005/11/30/1450.html</link><dc:creator>christanxw</dc:creator><author>christanxw</author><pubDate>Wed, 30 Nov 2005 10:30:00 GMT</pubDate><guid>http://www.cppblog.com/christanxw/archive/2005/11/30/1450.html</guid><wfw:comment>http://www.cppblog.com/christanxw/comments/1450.html</wfw:comment><comments>http://www.cppblog.com/christanxw/archive/2005/11/30/1450.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/christanxw/comments/commentRss/1450.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/christanxw/services/trackbacks/1450.html</trackback:ping><description><![CDATA[<A href="http://blog.csdn.net/christanxw/archive/2005/11/30/540364.aspx">http://blog.csdn.net/christanxw/archive/2005/11/30/540364.aspx</A><img src ="http://www.cppblog.com/christanxw/aggbug/1450.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/christanxw/" target="_blank">christanxw</a> 2005-11-30 18:30 <a href="http://www.cppblog.com/christanxw/archive/2005/11/30/1450.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>变态之MEMCPY</title><link>http://www.cppblog.com/christanxw/archive/2005/10/11/624.html</link><dc:creator>christanxw</dc:creator><author>christanxw</author><pubDate>Tue, 11 Oct 2005 03:02:00 GMT</pubDate><guid>http://www.cppblog.com/christanxw/archive/2005/10/11/624.html</guid><wfw:comment>http://www.cppblog.com/christanxw/comments/624.html</wfw:comment><comments>http://www.cppblog.com/christanxw/archive/2005/10/11/624.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.cppblog.com/christanxw/comments/commentRss/624.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/christanxw/services/trackbacks/624.html</trackback:ping><description><![CDATA[<P>void* mymemcpy( void* dest, const void* src, size_t count )<BR>{<BR>    char* d = (char*)dest;<BR>    const char* s = (const char*)src;<BR>    int n = (count + 7) / 8; // count > 0 assumed</P>
<P>    switch( count & 7 )<BR>    {<BR>    case 0:  do {  *d++ = *s++;<BR>    case 7:        *d++ = *s++;<BR>    case 6:        *d++ = *s++;<BR>    case 5:        *d++ = *s++;<BR>    case 4:        *d++ = *s++;<BR>    case 3:        *d++ = *s++;<BR>    case 2:        *d++ = *s++;<BR>    case 1:        *d++ = *s++;<BR>               } while (--n > 0);<BR>    }</P>
<P>    return dest;<BR>}<BR>这样也行，真是长见识了~_~<BR><BR>int n = (count + 7) / 8;计算要复制的轮数（每轮复制8位），剩下的余数位数也要复制进去。<BR>count & 7控制要复制余数位数，while (--n > 0)控制轮数。<BR>比如count = 9，则n = 2，count & 7  = 1，要复制2轮，程序跳到case1执行，复制一位之后，再循环一轮，复制8位</P><img src ="http://www.cppblog.com/christanxw/aggbug/624.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/christanxw/" target="_blank">christanxw</a> 2005-10-11 11:02 <a href="http://www.cppblog.com/christanxw/archive/2005/10/11/624.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eric Raymond对于几大开发语言的评价（转）</title><link>http://www.cppblog.com/christanxw/archive/2005/09/28/457.html</link><dc:creator>christanxw</dc:creator><author>christanxw</author><pubDate>Wed, 28 Sep 2005 01:04:00 GMT</pubDate><guid>http://www.cppblog.com/christanxw/archive/2005/09/28/457.html</guid><wfw:comment>http://www.cppblog.com/christanxw/comments/457.html</wfw:comment><comments>http://www.cppblog.com/christanxw/archive/2005/09/28/457.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/christanxw/comments/commentRss/457.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/christanxw/services/trackbacks/457.html</trackback:ping><description><![CDATA[<FONT face=宋体><SPAN lang=EN-US style="COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: Arial; mso-font-kerning: 0pt"><FONT size=3>Eric Raymond</FONT></SPAN><SPAN style="COLOR: black; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt; mso-bidi-font-family: Arial; mso-font-kerning: 0pt"><FONT size=3>是开源运动的领袖人物，对于<SPAN lang=EN-US>UNIX</SPAN>开发有很深的造诣，主持开发了<SPAN lang=EN-US>fetchmail</SPAN>。他的《大教堂与集市》被奉为开源运动的经典之作。下面对几大开发语言的评价非常中肯，是我近年来看到的比较出色的评论。特别是他评价中抱有的那种<SPAN lang=EN-US>“</SPAN>简单就 是好<SPAN lang=EN-US>”</SPAN>的思想，很值得我们深思。我特别选译出一些段落，供大家阅读思考。原文参见：</FONT><FONT size=3><SPAN lang=EN-US>http://www.catb.org/~esr/writings/taoup/html/ch14s04.html#c_language<BR></SPAN></FONT></SPAN><BR>C<BR><SPAN style="mso-spacerun: yes">    </SPAN><FONT size=3>虽说<SPAN lang=EN-US>C</SPAN>语言在内存管理方面存在严重的缺陷，不过它还是在某些应用领域里称王称霸。对于那些要求最高的效率，良好的实时性，或者与操作系统内核紧密关联的程序来说，<SPAN lang=EN-US>C</SPAN>仍然是很好的选择。</FONT></FONT><SPAN lang=EN-US><BR><FONT size=3><FONT face=宋体><SPAN style="mso-spacerun: yes">    </SPAN>C</FONT></FONT></SPAN><FONT face=宋体 size=3>良好的可移植性也为它加了分。不过现在很多其他的语言可移植性越来越好，<SPAN lang=EN-US>C</SPAN>在这方面的优势可能会逐渐丧失。</FONT><SPAN lang=EN-US><BR><SPAN style="mso-spacerun: yes"><FONT face=宋体 size=3>    </FONT></SPAN></SPAN><FONT face=宋体 size=3>现有的很多程序可以产生非常棒的<SPAN lang=EN-US>C</SPAN>代码，比如语法分析器、<SPAN lang=EN-US>GUI Builder</SPAN>等，这时候<SPAN lang=EN-US>C</SPAN>语言也是有吸引力的，因为你所需要编写的代码只是整个程序的一小部分。</FONT><SPAN lang=EN-US><BR><SPAN style="mso-spacerun: yes"><FONT face=宋体 size=3>    </FONT></SPAN></SPAN><FONT face=宋体 size=3>再有，我们当然应该认识道，<SPAN lang=EN-US>C</SPAN>语言对于程序员来说具有无可替代的价值。就我这里讨论的每一种语言而论，只要你发掘的足够深，到最后你会看到它们的内核都是用纯正的、可移植的<SPAN lang=EN-US>C</SPAN>写成的。</FONT><SPAN lang=EN-US><BR><SPAN style="mso-spacerun: yes"><FONT face=宋体 size=3>    </FONT></SPAN></SPAN><FONT face=宋体 size=3>到了今天这个时候，我们最好把<SPAN lang=EN-US>C</SPAN>看成是<SPAN lang=EN-US>UNIX</SPAN>虚拟机上的高级汇编语言。</FONT><SPAN lang=EN-US><BR><SPAN style="mso-spacerun: yes"><FONT face=宋体 size=3>    </FONT></SPAN></SPAN><FONT face=宋体 size=3>就算是其他的高级语言完全可以满足你的工作需要，抽出时间来学习<SPAN lang=EN-US>C</SPAN>语言也仍然有益，它能帮助你在硬件体系的层次上思考问题。</FONT><SPAN lang=EN-US><BR><SPAN style="mso-spacerun: yes"><FONT face=宋体 size=3>    </FONT></SPAN></SPAN><FONT face=宋体 size=3>即使到了今天，最好的<SPAN lang=EN-US>C</SPAN>语言教程仍然是<SPAN lang=EN-US>1988</SPAN>年出版的<SPAN lang=EN-US>K&R</SPAN>第二版</FONT><FONT size=3><FONT face=宋体><SPAN lang=EN-US>The C Programming Language.<BR><SPAN style="mso-spacerun: yes">    </SPAN></SPAN>总结：<SPAN lang=EN-US>C</SPAN>最出色的地方在于其高效和贴近机器，最糟糕的地方在它的内存管理地狱。</FONT></FONT><SPAN lang=EN-US><BR><BR><FONT size=3><FONT face=宋体><SPAN style="mso-spacerun: yes">    </SPAN>C++<BR><SPAN style="mso-spacerun: yes">    </SPAN>C++</FONT></FONT></SPAN><FONT face=宋体 size=3>最初发布于<SPAN lang=EN-US>1980</SPAN>年代中期，当时面向对象语言被认为是解决软件复杂性问题的银弹。<SPAN lang=EN-US>C++</SPAN>的面向对象特性看相去使其全面超越了<SPAN lang=EN-US>C</SPAN>，支持者认为<SPAN lang=EN-US>C++</SPAN>将迅速把上一代语言挤到陈列馆里去。</FONT><SPAN lang=EN-US><BR><SPAN style="mso-spacerun: yes"><FONT face=宋体 size=3>    </FONT></SPAN></SPAN><FONT face=宋体 size=3>但是历史并非如此。究其原因，至少有一部分归咎于<SPAN lang=EN-US>C++</SPAN>本身。为了与<SPAN lang=EN-US>C</SPAN>兼容，<SPAN lang=EN-US>C++</SPAN>被迫作出了很多重大的设计妥协，结果导致语言过分华丽，过分复杂。为了与<SPAN lang=EN-US>C</SPAN>兼容，<SPAN lang=EN-US>C++</SPAN>并没有采用自动内存管理的策略，从而丧失了修正<SPAN lang=EN-US>C</SPAN>最严重问题的机会。</FONT><SPAN lang=EN-US><BR><SPAN style="mso-spacerun: yes"><FONT face=宋体 size=3>    </FONT></SPAN></SPAN><FONT face=宋体 size=3>另外一部分原因，恐怕要算到面向对象身上。看起来<SPAN lang=EN-US>OO</SPAN>并没有很好的达成人们当年的预期。我就这个问题调研过，我发现使用<SPAN lang=EN-US>OO</SPAN>方法导致组件之间出现很厚的粘合层，并且带来了严重的可维护性问题。今天让我们来看看开放源码社区，你会发现<SPAN lang=EN-US>C++</SPAN>的应用还是集中在<SPAN lang=EN-US> GUI</SPAN>，游戏和多媒体工具包这些方面，在其他地方很少用到。要知道，面向对象也只是在这些领域被证明非常成功，而开放源码社区的选择，很大程度上体现了程序员的自由意志，而不是公司管理层的胡乱指挥。</FONT><SPAN lang=EN-US><BR><SPAN style="mso-spacerun: yes"><FONT face=宋体 size=3>    </FONT></SPAN></SPAN><FONT face=宋体 size=3>也许<SPAN lang=EN-US>C++</SPAN>实现<SPAN lang=EN-US>OO</SPAN>的方法有问题。有证据表明<SPAN lang=EN-US>C++</SPAN>程序在整个生命周期的开销高于相应的<SPAN lang=EN-US>C, Fortran</SPAN>和<SPAN lang=EN-US>Ada</SPAN>程序。不过，究竟这是否应该归咎与<SPAN lang=EN-US>C++</SPAN>的<SPAN lang=EN-US>OO</SPAN>实现上，还不清楚。</FONT><SPAN lang=EN-US><BR><SPAN style="mso-spacerun: yes"><FONT face=宋体 size=3>    </FONT></SPAN></SPAN><FONT face=宋体 size=3>最近几年，<SPAN lang=EN-US>C++</SPAN>加入了很多非<SPAN lang=EN-US>OO</SPAN>的思想，其异常思想类似<SPAN lang=EN-US>Lisp</SPAN>，<SPAN lang=EN-US>STL</SPAN>的出现是非常了不起的。</FONT><SPAN lang=EN-US><BR><SPAN style="mso-spacerun: yes"><FONT face=宋体 size=3>    </FONT></SPAN></SPAN><FONT face=宋体 size=3>其实<SPAN lang=EN-US>C++</SPAN>最根本的问题在于，它基本上只不过是另一种传统的语言。<SPAN lang=EN-US>STL</SPAN>中的内存管理比先前的<SPAN lang=EN-US>new/delete</SPAN>和<SPAN lang=EN-US>C</SPAN>的方案要好的多，但是还是没有解决问题。对于很多应用程序而言，其<SPAN lang=EN-US>OO</SPAN>特性并不明显，相比与<SPAN lang=EN-US>C</SPAN>，除了增加复杂度之外没有获得很多好处。</FONT><SPAN lang=EN-US><BR><SPAN style="mso-spacerun: yes"><FONT face=宋体 size=3>    </FONT></SPAN></SPAN><FONT face=宋体 size=3>总结：<SPAN lang=EN-US>C++</SPAN>优点在于作为编译型语言，把效率与泛型和面向对象特性结合起来，其缺点在于过于华丽复杂，倾向于鼓励程过分复杂的设计。</FONT><SPAN lang=EN-US><BR><BR><FONT size=3><FONT face=宋体><SPAN style="mso-spacerun: yes">     </SPAN>Java<BR><SPAN style="mso-spacerun: yes">    </SPAN>Java</FONT></FONT></SPAN><FONT face=宋体 size=3>的设计很聪明，它采用了自动内存管理，这是最大的改进，支持<SPAN lang=EN-US>OO</SPAN>设计带来的好处虽然不那么突出，不过也很值得赞赏，相比<SPAN lang=EN-US>C++</SPAN>，其<SPAN lang=EN-US>OO</SPAN>设计规模小而且简单 。</FONT><SPAN lang=EN-US><BR><SPAN style="mso-spacerun: yes"><FONT face=宋体 size=3>    </FONT></SPAN></SPAN><FONT face=宋体 size=3>相对于<SPAN lang=EN-US>Python</SPAN>而言，<SPAN lang=EN-US>Java</SPAN>有一些明显的失误。有些地方设计的还是太复杂，甚至有缺陷。<SPAN lang=EN-US>Java</SPAN>的类可见性和隐式<SPAN lang=EN-US>scoping</SPAN>规则太复杂了。<SPAN lang=EN-US>Interface</SPAN>机制是为了避免多继承带来的问题而设计的，但是要理解和使用它还是挺难。内部类和匿名类导致令人困惑的代码。缺乏有效的析构机制，使得除了内存之外的其他资源（比如互斥量和锁）管理起来很困难。<SPAN lang=EN-US>Java</SPAN>的线程不可靠，其<SPAN lang=EN-US>I/O</SPAN>机制很强大，但是读取一个文本文件却非常繁琐。</FONT><SPAN lang=EN-US><BR><FONT size=3><FONT face=宋体><SPAN style="mso-spacerun: yes">    </SPAN>Java</FONT></FONT></SPAN><FONT face=宋体 size=3>没有管理库版本的机制，从而形式上重蹈了了<SPAN lang=EN-US>Windows DLL</SPAN>地狱的覆辙。在类似应用服务器这样的环境里，这引起了大量的问题。</FONT><SPAN lang=EN-US><BR><SPAN style="mso-spacerun: yes"><FONT face=宋体 size=3>    </FONT></SPAN></SPAN><FONT face=宋体 size=3>总体而言，我们可以说除了系统编程和对效率要求极高的程序之外，<SPAN lang=EN-US>Java</SPAN>在大部分领域优于<SPAN lang=EN-US>C++</SPAN>。经验表明，<SPAN lang=EN-US>Java</SPAN>程序员似乎不太容易象<SPAN lang=EN-US>C++</SPAN>程序员那样构造过度的<SPAN lang=EN-US>OO</SPAN>层，不过在<SPAN lang=EN-US>Java</SPAN>中这仍然是个严重问题。</FONT><SPAN lang=EN-US><BR><FONT size=3><FONT face=宋体><SPAN style="mso-spacerun: yes">    </SPAN>Java</FONT></FONT></SPAN><FONT face=宋体 size=3>是否优于诸如<SPAN lang=EN-US>Perl, Python</SPAN>这样的语言？我们还不是很清楚，很大程度上似乎跟程序规模有关。其擅长的领域基本上于<SPAN lang=EN-US>Python</SPAN>相似，在效率上无法跟<SPAN lang=EN-US>C/C++</SPAN>相提并论，在小规模的、大量使用模式匹配和编辑的项目里也无法匹敌<SPAN lang=EN-US>Perl</SPAN>。在小项目里，<SPAN lang=EN-US>Java</SPAN>显得过分强大了。我们猜测<SPAN lang=EN-US>Python</SPAN>更适合小项目，而<SPAN lang=EN-US>Java</SPAN>适合大项目，不过这一点并没有得到有力的证明。</FONT><SPAN lang=EN-US><BR><BR><FONT size=3><FONT face=宋体><SPAN style="mso-spacerun: yes">    </SPAN>Python<BR><SPAN style="mso-spacerun: yes">    </SPAN>Python</FONT></FONT></SPAN><FONT face=宋体 size=3>是一种脚本语言，可以与<SPAN lang=EN-US>C</SPAN>紧密整合。它可以与动态加载的<SPAN lang=EN-US>C</SPAN>库模块交换数据，也可以作为内嵌脚本语言而从<SPAN lang=EN-US>C</SPAN>中调用。其语法类似<SPAN lang=EN-US>C</SPAN>和模块化语言的杂合，不过有一个独一无二的特征，就是以缩进来确定语句块。</FONT><SPAN lang=EN-US><BR><FONT size=3><FONT face=宋体><SPAN style="mso-spacerun: yes">    </SPAN>Python</FONT></FONT></SPAN><FONT face=宋体 size=3>语言非常干净，设计优雅，具有出色的模块化特性。它提供了面向对象能力，但不强迫用户进行面向对象设计。其类型系统提供了强大的表达能力，类似<SPAN lang=EN-US>Perl</SPAN>，具有匿名<SPAN lang=EN-US>lambda</SPAN>表达式，这点又让<SPAN lang=EN-US>Lisp</SPAN>黑客们感到亲切。<SPAN lang=EN-US>Python</SPAN>依靠<SPAN lang=EN-US>Tk</SPAN>提供方便的<SPAN lang=EN-US>GUI</SPAN>界面开发能力。</FONT><SPAN lang=EN-US><BR><SPAN style="mso-spacerun: yes"><FONT face=宋体 size=3>    </FONT></SPAN></SPAN><FONT face=宋体 size=3>在所有的解释型语言里，<SPAN lang=EN-US>Python</SPAN>和<SPAN lang=EN-US>Java</SPAN>最适合多名程序员以渐进方式协同开发大型项目。在很多方面， <SPAN lang=EN-US><SPAN style="mso-spacerun: yes">  </SPAN><SPAN style="mso-spacerun: yes"> </SPAN>Python</SPAN>比<SPAN lang=EN-US>Java</SPAN>要简单，它非常适合与构造快速原型，这一点使得它对于<SPAN lang=EN-US>Java</SPAN>有独特优势：对于那些既不很复杂，又不要求高效率的程序，<SPAN lang=EN-US>Python</SPAN>十分合适。</FONT><SPAN lang=EN-US><BR><FONT size=3><FONT face=宋体><SPAN style="mso-spacerun: yes">   </SPAN><SPAN style="mso-spacerun: yes"> </SPAN>Python</FONT></FONT></SPAN><FONT face=宋体 size=3>的速度没法跟<SPAN lang=EN-US>C/C++</SPAN>相比，不过在今天的高速<SPAN lang=EN-US>CPU</SPAN>上，合理地使用混合语言编程策略使得<SPAN lang=EN-US>Python</SPAN>的上述弱点被有效地弥补。事实上，<SPAN lang=EN-US>Python</SPAN>几乎被认为是主流脚本语言中最慢的一个，因为它提供了动态多态性。在大量使用正则表达式的小型项目，它逊于<SPAN lang=EN-US>Perl</SPAN>。对于微 型项目而言，<SPAN lang=EN-US>shell</SPAN>和<SPAN lang=EN-US>Tcl</SPAN>可能更好，<SPAN lang=EN-US>Python</SPAN>显得太过强大了。</FONT><SPAN lang=EN-US><BR><SPAN style="mso-spacerun: yes"><FONT face=宋体 size=3>    </FONT></SPAN></SPAN><FONT size=3><FONT face=宋体>总结：<SPAN lang=EN-US>Python</SPAN>最出色的地方在于，它鼓励清晰易读的代码，特别适合以渐进开发的方式构造大项目。其缺陷在于效率不高，太慢，不但跟编译语言相比慢，就是跟其他脚本语言相比也显得慢。<SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></FONT></FONT><img src ="http://www.cppblog.com/christanxw/aggbug/457.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/christanxw/" target="_blank">christanxw</a> 2005-09-28 09:04 <a href="http://www.cppblog.com/christanxw/archive/2005/09/28/457.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在C++中使用接口</title><link>http://www.cppblog.com/christanxw/archive/2005/09/24/417.html</link><dc:creator>christanxw</dc:creator><author>christanxw</author><pubDate>Sat, 24 Sep 2005 11:36:00 GMT</pubDate><guid>http://www.cppblog.com/christanxw/archive/2005/09/24/417.html</guid><wfw:comment>http://www.cppblog.com/christanxw/comments/417.html</wfw:comment><comments>http://www.cppblog.com/christanxw/archive/2005/09/24/417.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/christanxw/comments/commentRss/417.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/christanxw/services/trackbacks/417.html</trackback:ping><description><![CDATA[面向对象的语言诸如JAVA提供了Interface来实现接口，但C++却没有这样一个东西，尽管C++通过纯虚基类实现接口，譬如COM的C++实现就是通过纯虚基类实现的（当然MFC的COM实现用了嵌套类），但我们更愿意看到一个诸如Interface的东西。下面就介绍一种解决办法。<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"><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Interfaces.h<BR></SPAN><SPAN style="COLOR: #008000">//<BR></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">#define</SPAN><SPAN style="COLOR: #000000"> Interface class</SPAN><SPAN style="COLOR: #000000"><BR><BR></SPAN><SPAN style="COLOR: #0000ff">#define</SPAN><SPAN style="COLOR: #000000"> DeclareInterface(name) Interface name { \</SPAN><SPAN style="COLOR: #000000"><BR>          </SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">: \<BR>          </SPAN><SPAN style="COLOR: #0000ff">virtual</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">~</SPAN><SPAN style="COLOR: #000000">name() {}<BR><BR></SPAN><SPAN style="COLOR: #0000ff">#define</SPAN><SPAN style="COLOR: #000000"> DeclareBasedInterface(name, base) class name :</SPAN><SPAN style="COLOR: #000000"><BR>        </SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">base</SPAN><SPAN style="COLOR: #000000"> { \<BR>           </SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">: \<BR>           </SPAN><SPAN style="COLOR: #0000ff">virtual</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">~</SPAN><SPAN style="COLOR: #000000">name() {}<BR><BR></SPAN><SPAN style="COLOR: #0000ff">#define</SPAN><SPAN style="COLOR: #000000"> EndInterface };</SPAN><SPAN style="COLOR: #000000"><BR><BR></SPAN><SPAN style="COLOR: #0000ff">#define</SPAN><SPAN style="COLOR: #000000"> implements public</SPAN><SPAN style="COLOR: #000000"><BR><BR></SPAN></DIV><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"><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> IBar.h<BR></SPAN><SPAN style="COLOR: #008000">//<BR></SPAN><SPAN style="COLOR: #000000"><BR>DeclareInterface(IBar)<BR>   </SPAN><SPAN style="COLOR: #0000ff">virtual</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> GetBarData() </SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>   </SPAN><SPAN style="COLOR: #0000ff">virtual</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> SetBarData(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> nData) </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>EndInterface<BR></SPAN></DIV>是不是很像MFC消息映射那些宏啊，熟悉MFC的朋友一定不陌生。<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"><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Foo.h<BR></SPAN><SPAN style="COLOR: #008000">//<BR></SPAN><SPAN style="COLOR: #000000"><BR>#include </SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">BasicFoo.h</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000"><BR>#include </SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">IBar.h</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000"><BR><BR></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> Foo : </SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000"> BasicFoo, implements IBar<BR>{<BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Construction & Destruction</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">:<BR>   Foo(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> x) : BasicFoo(x)<BR>   {<BR>   }<BR><BR>   </SPAN><SPAN style="COLOR: #000000">~</SPAN><SPAN style="COLOR: #000000">Foo();<BR><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> IBar implementation</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">:<BR>   </SPAN><SPAN style="COLOR: #0000ff">virtual</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> GetBarData() </SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000"><BR>   {<BR>      </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> add your code here<IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">   }<BR><BR>   </SPAN><SPAN style="COLOR: #0000ff">virtual</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> SetBarData(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> nData)<BR>   {<BR>      </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> add your code here<IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">   }<BR>};<BR><BR></SPAN></DIV>
<P>怎么样，很简单吧，并不需要做很多的努力我们就可以在C++中使用接口了。然而，由于这并不是语言本身所直接支持的特性，所以我们需要遵循一些规则：<BR>         a)   声明一个类的时候，如果你的类除了要从接口类继承外还要从另一个类继承(结构上的继承，即is a关系)，则把这个类作为第一个基类，就像我们平时做的一样，譬如CFrameWnd从CWnd继承，<FONT face="Courier New">CBitmapButton</FONT>从CButton继承，CMyDialog从CDialong继承。当你要从MFC类派生的时候，这尤其重要，把他们声明为第一个基类以避免破坏MFC的RuntimeClass机制。<BR>         b)   其他的基类紧跟其后，有多少就跟多少，如果你需要的话。譬如：<FONT face="Courier New">class Foo : public BasicFoo</FONT>, implements <TT>IBar</TT>, implements <TT>IOther</TT>, implements <TT>IWhatever</TT>, ...<BR>         c)   接口类里面不要声明任何成员变量。接口类仅用于描述行为而不是数据。当你要作多重继承时，这样做可以避免数据成员被从同一个接口类多次继承。<BR>         d)   接口类的所有成员函数定义为纯虚函数。这可以确保你的实现类来实现这些函数的全部，当然你也可以在抽象类实现部分函数，只要在你的派生类里实现剩下的函数。<BR>         e)   不要从除了接口类的其他任何类派生你的接口类。<FONT face="Courier New">DeclareBasedInterface()可以做到这个.普通类可以选择实现基接口还是派生的接口，后面一种意味着两者都要实现。<BR>   f) 将一个指向实现接口的类的指针赋值给一个指向该接口类的指针是不需要强制类型转换的，但反过来将一个接口类的指针赋值给一个实现该接口的类的指针就需要一个显式的强制类型转换。事实上我们可能会使用多重继承，这样这些转换我们就不能使用老式的转换。不过使用运行时类型信息(使用/GR选项)和动态类型转换可以很好的工作当然也更安全。<BR>   g) 此外dynamic_cast为你提供了一种查询一个对象或接口是否实现了一个指定的接口的途径。<BR>   h) 你还要非常小心的避免不同接口函数的命名冲突。</FONT></P>
<P>如果你仔细观察<FONT face="Courier New">DeclareInterface</FONT> 和 <FONT face="Courier New">DeclareBasedInterfaca宏你会发现有一个操作是必须的：每个接口类都有一个虚析构函数。你可能认为这不重要，但是如果没有这个就可能会导致一些问题，看看下面的例子：</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"><SPAN style="COLOR: #000000">DeclareInterface(IBar)<BR>   </SPAN><SPAN style="COLOR: #0000ff">virtual</SPAN><SPAN style="COLOR: #000000"> LPCTSTR GetName() </SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>   </SPAN><SPAN style="COLOR: #0000ff">virtual</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> SetName(LPCTSTR name) </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>EndInterface<BR><BR></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> Foo : implements IBar<BR>{<BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Internal data</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">:<BR>   </SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> m_pName;<BR><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Construction & Destruction</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">:<BR>   Foo()<BR>   {<BR>      m_pName </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> NULL;<BR>   }<BR><BR>   </SPAN><SPAN style="COLOR: #000000">~</SPAN><SPAN style="COLOR: #000000">Foo()<BR>   {<BR>      ReleaseName();<BR>   }<BR><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Helpers</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #0000ff">protected</SPAN><SPAN style="COLOR: #000000">:<BR>   </SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> ReleaseName()<BR>   {<BR><BR>      </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (m_pName </SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000"> NULL)<BR>         free(m_pName);<BR>   }<BR><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> IBar implementation</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">:<BR>   </SPAN><SPAN style="COLOR: #0000ff">virtual</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> GetName() </SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000"><BR>   {<BR>      </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> m_pName<BR>   }<BR><BR>   </SPAN><SPAN style="COLOR: #0000ff">virtual</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> SetName(</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> name)<BR>   {<BR>      ReleaseName();<BR>      m_pName </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> _strdup(name);<BR>   }<BR>};<BR><BR></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> BarFactory<BR>{<BR></SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">:<BR>   </SPAN><SPAN style="COLOR: #0000ff">enum</SPAN><SPAN style="COLOR: #000000"> BarType {Faa, Fee, Fii, Foo, Fuu};<BR><BR>   </SPAN><SPAN style="COLOR: #0000ff">static</SPAN><SPAN style="COLOR: #000000"> IBar CreateNewBar(BarType barType)<BR>   {<BR>      </SPAN><SPAN style="COLOR: #0000ff">switch</SPAN><SPAN style="COLOR: #000000"> (barType)<BR>      {<BR>         </SPAN><SPAN style="COLOR: #0000ff">default</SPAN><SPAN style="COLOR: #000000">:<BR>         </SPAN><SPAN style="COLOR: #0000ff">case</SPAN><SPAN style="COLOR: #000000"> Faa:<BR>            </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000"> Faa;<BR>         </SPAN><SPAN style="COLOR: #0000ff">case</SPAN><SPAN style="COLOR: #000000"> Fee:<BR>            </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000"> Fee;<BR>         </SPAN><SPAN style="COLOR: #0000ff">case</SPAN><SPAN style="COLOR: #000000"> Fii:<BR>            </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000"> Fii;<BR>         </SPAN><SPAN style="COLOR: #0000ff">case</SPAN><SPAN style="COLOR: #000000"> Foo:<BR>            </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000"> Foo;<BR>         </SPAN><SPAN style="COLOR: #0000ff">case</SPAN><SPAN style="COLOR: #000000"> Fuu:<BR>            </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000"> Fuu;<BR>      }<BR>   }<BR>};<BR><BR></SPAN></DIV></FONT>就像你看到的一样，这里有一个类工厂，它根据BarType来创建一个IBar的实现，当你使用完以后你当然希望要delete该对象，你会像下面这样做：<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"><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> main()<BR>{<BR>   IBar</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> pBar </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> BarFactory::CreateBar(Foo);<BR><BR>   pBar</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">SetName(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">MyFooBar</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>   </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Use pBar as much as you want,<BR>   </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> <IMG src="http://www.cppblog.com/images/dot.gif"><BR><BR>   </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> and then just delete it when it's no longer needed</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">   delete pBar;    </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> Oops!</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">}<BR><BR></SPAN></DIV>delete pBar 做了什么取决于该对象是否有一个虚析构函数。如果Foo没有一个虚析构函数，则只有IBar 的隐式的空析构函数被调用，Foo的析构函数不会被调用，这样就发生了内存泄露。接口类里虚析构函数的声明避免了这用状况，它确保每个实现接口的类都有一个虚析构函数。<BR><BR>当你使用DeclareInterfac的时候，记得使用EndInterface和它匹配。Interface 宏和 implements宏仅仅是代替了class和public，这看起来是多余的，但我认为它们更明确的表达了代码的意图。如果我这么写：class <FONT face="Courier New">Foo : public IBar，你可能认为这只是一个简单的继承；但如果我这么写：class Foo: implements IBar，你就会看到它实际的价值和意图---这是对一个接口的实现，而不是简单的一次继承。</FONT><img src ="http://www.cppblog.com/christanxw/aggbug/417.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/christanxw/" target="_blank">christanxw</a> 2005-09-24 19:36 <a href="http://www.cppblog.com/christanxw/archive/2005/09/24/417.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>