Object Magazine对Bjarne Stroustrup的专访

马皓明 翻译  荣耀 指导  

Object Magazine Online:请问您最喜欢的软件工具或者开发环境是什么?其实我应该先问您最喜欢哪种编程语言,但那多少显得有些多余。

BS:或许吧。C++确实是我最喜欢的编程语言。然而,我们应该时刻铭记,有趣且有用的编程语言有很多种。只懂一门编程语言的人是不应该以一名专业程序员或设计师自居的。学习新的编程语言或编程技术总是让人快乐。但我们应该努力避免过分热衷于试验新工具、语言和技术。

Unix仍是我最喜欢的开发环境。

OMO:我也喜欢C++语言。至于专用语言,我刚刚使用perl的模式匹配和报表编写功能为comp.object FAQ开发了一个新的Web版,它比我用C或C++编写进展要快得多。尽管我明白PC自有它的市场,我还是更喜欢Unix,我也成长于Unix。

请问您最喜欢什么模式?

BS:我(至今仍然如此?)不使用具名模式来思考,我以技术和基本示例的方式进行思考。不过,我常常使用“factory”模式。这种模式特别之处在于允许我创建一个未知的派生类对象,这只需要几行了解一个公共的(更加一般化的)基类的代码即可。再加上抽象类的广泛使用,这个模式让我可以编写出只直接依赖抽象类的应用代码,从而,我就可以写出环境依赖最小且定义良好的应用程序和库模块。C++社群对factory模式的一个传统命名变体是“虚构造器”。

OMO:我已经在许多场合使用了虚构造器,看来它们非常有用。请问您最喜欢的组件模型是什么,您认为哪一种会最终胜出?例如CORBA、DCOM、OpenDoc和Beans/RMI等等。

BS:我没有什么最喜欢的组件模型。我一直希望出现更优雅且(或)更加一般化的模型。上边提到的那些都显得太庞大、太复杂、太难用、太难与编程语言集成、太专有或开销太大而不够理想。

噢不,我并没有一种替代方案。在我看来还缺少一些基础性的东西,但我一直没能进行这方面工作。我正在寻找这样的东西:允许同步调用与异步调用平稳并存,可以与多种编程语言紧密集成,另外,装载于单个地址空间的模块之间可以像两个被编译在一起的类那样高效通信。如果全部表达出我们对组件模型的要求,那它肯定非常复杂,但这种复杂性难道真的必须暴露给一个新手、暴露给做某项本质上很简单的工作的人吗?我表示怀疑。

OMO:真是精彩的观点。请问您最喜欢的软件方法学是什么?还有,您如何看待UML?

BS:就我个人来说我不使用图表,我读过的少量有关UML的东西透着一股让人不舒服的“救世主”的腔调,这模糊了其技术内容。这或许是一个合适的“杀死报信的”案例,因为其基本思想看来还是蛮好的。

等我得空时我会看看UML能否简单而精确地模塑出C++标准库。如果可以,它应该有能力处理许多未来会变得很有意思的东西;如果不行,那它对“软件为何物”的认识就是有局限的。STL(容器、算法及迭代器框架)是一个从各独立部分构成软件优雅的复合体的优秀试验。

OMO:这个看法很妙。我想我们常常听到的只是大肆的宣传与良好的心愿,比如组件模型。在当今软件开发中,您认为方法学扮演着一个多么重要的角色?我知道您在《The C++ Programming Language》1中讨论过这个话题,您能否简要地概括一下您最新的观点呢?

BS:把关于设计的讨论缩减到一章(伴有两个关于示例的支撑章)是最低限度的要求,不能再少了!我认为,一切软件开发的焦点必须集中于概念和对应用域的理解。

Java与我理想中的“通用编程语言”差得太远了。

对较大项目而言,被我们称为方法(methods)的各种规则和过程是必需的,而对于较小的项目,不甚严格的途径(approaches)通常更可取。为了试图补偿“方向性”、“在建系统的概念框架”以及“编程中用到的思想”等方面的缺乏,“方法”使用得太过频繁了。方法并非思考和理解的替代品。方法的运用应该足够灵活,以适应形形色色的管理者、设计师以及程序员群体的不同的才干、口味及弱项。

也就是说,我喜欢大致沿袭Booch的设计方式 — 或许对一般概念和静态结构的强调甚于时髦的东西。欲知详情,请参阅《The C++ Programming Language》(第三版)第四部分。

OMO:请问您最喜欢什么操作系统,您日常工作用的是什么电脑?

BS:在一台古老的SPARC工作站和一台SGI机器上用的是UNIX,我的膝上电脑上用的是Windows 95和NT。

OMO:请问您是个网上冲浪老手吗?

BS:我是个Web用户。我每天大约要访问一打的站点,但Web并非我生活的中心。Email对我来说仍然是重中之重。我下载零星的技术文章,购买一些古怪的玩意,但是我在网上找到的很多信息都过于零散,不够可靠,不适合用作真正的学习材料。我猜想Web在很短一段时间内就成了我一个宝贵的资源,可是在任何本质的问题上我仍然不依赖它。

我维护了一系列有着大量C++信息的主research.att.com/~bs。你在那儿可以找到我的一些论文、所著书籍的简要说明、勘误表、一个FAQ、C++相关站点链接,等等。

OMO:谢谢您介绍的参考信息,它将被加入OO FAQ附录E中J。请问您如何看待Java?

BS:我不怎么关心它。它是一种相当无趣的语言并是一个非常有趣的社会学现象,但它与我的专业兴趣关系不大。

执意要拿Java与C++对比的人可以去看看《The Design and Evolution of C++2中我对C++的设计标准。他们将会发现Java与我理想中的“通用编程语言”差得太远了。

OMO:我总看到Java拥有关于图形和Web方面的库,您认为其他语言在这些方面有用武之地吗?

BS:包括C++吗J 这毫无疑问。没有任何一种编程语言能够全部满足当今程序员五花八门的需要。理论上,可以存在单独一门通用编程语言。然而,我认为侧重点的差异、智力传统的差异以及个人偏好的差异将会造成多门这样的语言并存。另外,专用语言是永远不会供过于求的。

同时,了解多门语言很有意思,而且对你不无裨益。

OMO:我以前也听过这种说法,学习多门语言可以避免因某一门而导致思维定势,这是一条优秀的普遍法则。请问您认为目前Microsoft和Sun关于Java的论战会造成什么结果?

BS:这场“论战”相当不光彩,但无疑会促发Sun把Java确立为Windows的一种可选平台和一门排斥所有其他语言的编程语言。这事实上是一场不惜一切代价的“口粮之争”。双方都不会因此增光添彩,而无辜的旁观者却可能受到伤害(尽管C++社群似乎大体上没受影响,并且照常持续发展)。

我想结果会催生出几个大致兼容的Java变体以及相当数量的平台专属库。Sun、微软(可能还有其他人)都希望Java是平台中立的,但在他们自己的平台比在竞争者的平台上要运行得更好。这就会造成原本的“平台中立”对于复杂应用来说仍然只是一个捉摸不定的目标。

OMO:最新的第三版《The C++ Programming Language》我也有一本,它是K&R的《The C Programming Language》的著名“接班人”。这是不是最终版呢,您能否告诉我们一些相关消息?

BS:噢,你不可能为一门活跃的语言写一本最终版。但是,我们现在有了一份ISO C++标准,因此第三版的主题内容要比前两版更具持久力。第一版使用寿命有五年多,而当也十分畅销的第二版存活到第六个年头时,第三版出版了。据此预测第三版的使用寿命最少为七年似乎不无道理。

我想第三版的真正重要之处在于C++支持的编程技术已经成熟了。语言特性本身是没趣的,真正有趣的是这些特性所支持的编程和设计技术,是使用这些特性来编写优雅、高效且维护性强的系统的方式。

第三版的首要目标是作为有经验的程序员以及希望跟上近几年所有新生事物的C++程序员的一个引介者。与通常提供给新手的便当相比,它更适合于有经验的程序员。我努力避免贬低读者的智力水平。第三版也可以作为一本用户级的参考书,因为它展示了所有主要语言特性和标准库设施。我想,关于“如何高效地使用C++”已经有了如此之多的研究,很多人对C++的观点都已彻底过时了。

噢,你不可能为一门活跃的语言写一本最终版的书。

第三版描述了人们希望从一本摩登C++书籍获知的所有新语言特性:异常、模板、运行时类型识别(RTTI)、名字空间,等等。它还描述了所有新的库设施:容器、算法、数值支持、字符串、参数化的输入/输出流,等等。不过,我所强调的是这些设施支持的编程和设计技术。另外,我也没遗漏那些基本内容:C兼容性、使用C时常用的编程风格、具体类与抽象类的用法、使用类继承层次编程,等等。

我发现C++现在是一门使用起来更加方便、描述起来更加容易的语言了,借此优势我可以更易为人理解的方式而展示它,对此,新标准库功不可没。

OMO:您提到C++是一门“活跃的语言”,就是说它可以持续地发展变化。将来(可能)出现一套新标准吗?C++在哪些方面仍然活跃(正在变化)?

BS:所有ISO标准每隔五年都会进行一次修订、重新确认或被撤消。我毫不怀疑从现在起六年之后标准会发生变化。在这五年周期内,我们需要发展一种机制,用以处理缺陷报告并解决这些报告指出的现存问题。

我的意思是说,人们用C++已完成了如此多的工作和试验,如果经过了一段由标准带来的稳定期之后不再发生变化了,那是令人难以相信的。即便别的方面没变化,大量新技术也将发展起来,同时很多有趣的库将被大量使用。即使在语言定义方面没有变化,这些活动也会明显影响描述和教授一门语言的方式。

OMO:请问您认为在当今计算行业最具影响力的是什么?您只需提及几项中意东西的名字就可以了。

BS:或者是几项villans?或许最具影响力并且最具破坏力的趋势就是对计算技术降格的普遍深入的推进。我们似乎没有能力培养出足够多的聪明人来构建优秀的系统,而为了尽快交付系统而不停的催逼更导致雪上加霜。

这么一来,一方面,我们可以为那些对应用领域了如指掌的合格的系统构建师购买更好的开发工具,另一方面,可以尽力使我们的工具简单化、傻瓜化,以便那些不怎么聪明且没受那么多教育的人也能生产出尚可被接受的产品。我怀疑后一种情况更加普遍,这不可避免地导致了可靠性极差的“浮肿软件”但凡反对这种趋势的东西均在我的“中意列表”之中。

所有针对不同智力水平的良好教育实践都位于我这个列表的顶端,我这么做的用意并非推崇“技术降格”,而是对聪明人提出“理论与实践紧密结合”这一强烈要求。“模式运动(the patterns movement)”以及“对优良设计的提倡”是很值得称道的。我认为更优秀的编程语言是问题解决方案的一个方面,它们也只能充当一个方面。某些人以为一门优秀的编程语言可以“解决软件危机”,可惜这种观点不过是蛊惑人心罢了。总之,“一门优秀编程语言由什么构成”这个问题牵扯着“政治性”问题以及许多确实难上加难的问题。

OMO:我也赞同教育和高级学习处于最前线在我上次讲授一门C++/UML课程的时候,我总想谈一些更加复杂的话题,比如“经由虚继承的同属通信”,或者“DMI与class组合解决方案惯用法”,而听众是刚开始学习“什么是类”的学生。可能我有些扯远了,但我确实是在合适的情境下插入合适的示例的。

BS:在给新手讲东西时我们应该多加小心,即便是对一个有经验但对C++来说属于新手的程序员也是一样应该先辅以简单的示例阐明一系列连贯的概念,然后再考虑深入真正高级的主题

记得我在学习Ada时都快要绝望了,因为给我讲课的那些Ada高手们出言必是互相吹嘘“他们对Ada的理解是多么多么地深入”,或是“他们所能解决的问题是如何如何之复杂”。我当时就想,“如果这些就是理解并使用Ada所需要掌握的内容的话,真不敢保证我能继续学下去”。于是,我就确信他们只不过是在卖弄,而问题实际上比它们看上去要简单得多了。

OMO:您认为C++是否会在Web计算领域大显身手?它又是如何做到的?

BS:C++应该做得到,而且并不困难。我认为,随着服务设施的成熟,C++的灵活性、高效性及其应对复杂问题的便利设施都将成为致胜法宝。然而,只有当出现一些人,他们以“使C++在Web计算领域大显身手”作为本职工作,那时才可能得以实现。要解决Web相关问题,我们需要的是C++库。假若没有基础库的支持,使用专用工具和语言会更简单一些。我不知道这类C++ Web-service支持库是否已经存在或正被建造中,但我很高兴看到这类库的出现。

OMO:Mike关于这个问题的一篇文章向我们引介Object Media,那里有一些用C++实现的核心Java库。

您对将来这类模型的样子是否有一些想法呢?比如,对比Java的做法:它在需要时把applet传入浏览器;或者对比CGI的做法:它运行在一台服务器上,使用动态HTML与用户通信。您认为Web编程的未来会是怎样,或者C++应该在哪些方面担任重要角色?

BS:对此,我宁愿不做详细说明,因为我没有足够的知识确信任何一种情况。C++看起来很适合做服务器端的工作,不过,它需要一些库来确保服务提供者在平均时耗水平下能有效地支持诸如页面显示、简单动画或统计信息收集这类常见操作。

你可以使用C++解释器和其他机制来允许C++代码的下载。然而,我对从服务器端下载到本地机器上的代码是不放心的,不论是何种语言编写的代码。

安全性议题的难度大于多数人乐于相信的程度,而且重要性也超乎人们的想象。随着越来越多的金钱开始向Web穿流,越来越多的骗子会发觉投入时间于“开发吸引钱流所需要的各种工具和技巧”是值得的。同时,随着我们在电脑上放置的信息越来越多,我们的个人网络生活变得越来越容易受到病毒等东西的攻击。我计划不久后在电脑里存放我的很多照片还有不少财务记录。我担心这些个人信息会被自己意外破坏,而更令我忧心忡忡的是:世界上随便某个人的某段代码是否会那么做。

我认为用于代码下载的理想语言应该远比现在讨论和使用的语言更简单、威力更小:“失去知觉”应该是衡量某物能否穿过防火墙的一个合理标准,而我们都应该装配防火墙。你的公司允许applet穿过防火墙吗?JavaScript呢?动态HTML呢?Visual Basic宏呢?

OMO:精彩的观点,我们都该开始加倍小心了。既然C++的标准化工作已经全部结束,您对工作成果的满意度有多高呢?

BS:我对标准化后的C++非常满意。我知道如何实现的主要特性一项都不缺,我认真考虑后打算移除的特性一项都没有提供。

尤为特别的是,我们(即C++标准委员会成员,我是其中的一个活跃分子)成功接受了包含“高效且类型安全的容器”(诸如vector、list、map)以及“基础算法”(诸如find、sort、accumulate)的STL框架,对此我非常满意。这弥补了通常交付的C++实现中最扎眼的漏洞。直到现在,我们才真正拥有了一套标准容器。

标准库也使教授C++的难度大大降低了。我们“不得不先接触低阶的指针操作以便适应C风格数组和字符串”的日子一去不复返了。取而代之的是,我们可以先使用合适的容器类型和string,这样就可以将对低阶概念的讨论推迟到学生们做好与其打交道的准备之后进行。

重要的是,这些标准容器和string类自己管理存储空间,而且在需要的时候能自动扩充。这意味着,对于简单程序来说,“内存管理”变得完全自动化了;而对大型系统而言,工作难度也大大降低了。

自然,《the C++ Programing Language》第三版对此予以一定程度的细节解释。另外,能够更轻松地引入各种概念也是仰仗标准库的功劳。

OMO:您下一步计划是什么?会有“另一个C++”吗?您会开发另一门语言吗?

BS:我设计C++是因为当时找不到一门编程语言可以满足我的需要。只有当我再次遇到一个问题,而现有的语言中没有一种能充当解决它的良好工具或方法时,我才会考虑设计另一门语言。对于我在日常工作中面对的绝大多数问题,C++都是一个绝好的解决方案;而少数不合适的工作也都存在替代方案。

目前,我正致力于AT&T内部的几个项目。部分目的是,我可以尽力拓宽我的经验范围,同时借以了解那些新的有趣的问题。AT&T的网络是世界上最大、最复杂而且最可靠的分布式系统之一。随着电讯业的飞速发展,其中不乏有趣的问题。

OMO:C++标准中添加了许多新内容,例如“templates for casting”,包括语言已有的“经检查的向下转型(checked downcasting)”。我想应该称它们为static casts和dynamic casts。请问是您设计了这个新符号吗?为什么需要它们?

BS:是的,我是dynamic_cast语法设计者之一,设计它是为了与有着明确资格修饰的模板函数调用语法相对应。我与来自HP的Dmitry Lenkov合作,我们是运行时类型识别(RTTI)机制的提案人。

OMO:请问您是一个超级“流”爱好者吗?

BS:我是流库的设计者之一,我认为其中蕴含的一般概念最吸引人。

RTTI很容易被滥用。然而,在松耦合系统设计中,需要在独立开发的子系统之间传递对象,则必须使用RTTI。为了避免处理被传递对象时极易发生的误用,我们将dynamic_cast设计成能够恢复足够类型信息的理想机制。如果你把系统的主要接口设计为抽象类,当在模块之间进行通信时,你需要dynamic_cast操作来识别对象提供的是哪个接口(抽象类)。

OMO:这就意味着,在子系统间通信或设计子系统接口时,不能使用具体类型,作为参数而被传递的对象必须先向上转型为某个公共抽象基类(然后被传递进子系统接口的方法),一旦穿过“围墙”,再向下转型为基类的某派生具体类的实例以支持(继承而来的)接口,于是,以一系列公共的(可向下转型的)接口(抽象基类)传递进来的参数,(公共基类接口中的未定义但派生类中定义了的)特化函数就也可以被调用了。若您讲的意思我没理解错的话,似乎需要两套公共接口,一套定义子系统间的通信方式,另一套定义在子系统之间传递的公共对象。

BS:是这样的。首先要注意的是,向上转型是隐式自动进行的;其次,我预想模块间的交互接口常常是抽象类,它们构成应用程序的关键接口。请参考D&E或第三版《The C++ Programming Language》中的Io_obj示例。那个例子展示了怎样将系统接口和RTTI“深深地掩埋”于一个跨进程通讯系统的实现中的。编写一个应用程序时,差不多只使用它自己的协议(接口)就可以了,而与底层系统打交道的部分能够被完全局部化。

这实际上与我说过的factory模式有十分紧密的联系,关键之处在于使运行时可能变化的东西的接口成为抽象的。

OMO:请问您是一个超级“流”爱好者吗?

BS:你是指C++标准库里的iostreams吧?我想我是。我是流设计者之一,我认为其中蕴含的一般概念最吸引人。它具备固有的类型安全性、可扩展性、简洁性以及高效性。几年来,尽管流库积聚了一些工具,但那些过分夸大的iostreams库是否在基本概念上具有固有的效率仍然尚待观察。我认为目前的实现显然尚有改进余地。例如,没理由让一个简单的“Hello, World!”程序占几十K字节。

OMO:谢谢。我刚才提到的正是流的一般概念,我感觉它们非常优雅,而且可以作为I/O机制之外的一个隐喻。string(字符串流)就是一个最简单的例证。相比以前使用的继承方式,您是否更偏爱C++标准库现在使用的泛型函数方式呢?我曾听您谈起过,以这种“参数化的多态性”形式代替包含方式(inclusion)可以提升效率,却的确导致出现过多的一般函数。对此您还有其他看法吗?

BS:我是将STL引入标准库的主要支持者之一。我认为“泛型容器-迭代器”方案优雅地解决了以前其他方案中的问题。TCPL第三版第16章(标准库相关章节的第一章)对此进行了详细解释。

最主要的是,STL方案让我们在使用简便、最佳化且类型安全的容器的同时还能编写出适用于多种容器的代码。例如,一个遍历算法可以同时适用于vector和list,而且无须为元素访问操作支付调用虚函数的开销。

你说的“过多的一般函数”指的是代码复制开销,还是必须为每种容器都提供一大套函数?代码复制可以通过优化设计去除,而我并不认为编写一个符合标准的容器比编写一个其他任何具有“工业强度”的容器要做更多工作。关键的好处在于我们无需为每种容器重复编写算法。另外,在不严格苛求效率时,我们可以只构建一个满足标准对容器之基本要求的“传统”容器类,然后就能基于它使用继承机制了。

OMO:我正在思考在使用基类方法和使用一般函数、泛型函数表达算法的共通性之间的区别,我想两种方式的主要区别在于算法是在一个公共基类中实现还是在一个函数中实现。我认为两者的思想是一致的,但结构有所差异。两种方式看上去等价。使用继承的方式可被归类为Template Pattern,这或许是我最喜爱的模式了,尤其在构建框架的时候。

您认为任务(或线程)应该在一门编程语言直接支持的范围内吗?C++不直接支持它们,由此用户就能自由选择他们使用的模型,我这种看法对吗?

BS:你说的完全正确。我知道的支持并发的合理模式太多了,以至我无法找出单独一种合适的加入C++中。一些人需要的是“非抢先式线程”以支持最高效最基本的并发机制,一些人需要的是pre-emptable线程,另外一些人则需要full-blown进程,还有一些人需要能保证一个分布式系统中事务完整性的并发机制。我曾希望通过包含一套基本并发机制,使C++支持一些基本的并发模式,以满足用户的所有需求。然而,我永远都无法找到我认为能够充分满足C++社群中多数人要求的这么一套东西

最终结果就是在C++中并存多种处于竞争地位的并发模型。请参考《Parallel Programming Using C++》3(作者Gregory V. Wilson,编辑Paul Lu)一书中的示例。这本书描述了在C++中实现并发的多种方式。

OMO:谢谢您提供的参考书。它的技术独特性也将被加入到Object FAQ中。Java提供单继承和多接口继承,而C++提供多继承(和抽象类),这种机制是类型与实现的联合。不幸的是,我曾听到现在学校里称多继承是一个坏主意,而且我曾与一位构架师讨论过,他认为多继承会由于父类随着时间分别进化而导致维护困难。您对以上观点有何看法?

BS:每种有用或威力强大的特性都可能被误用,一门语言未提供的所有特性都被该语言的支持者们倾向于认为是“危险的”。你使用多继承可能会写出糟糕透顶的程序,正像你使用单继承或压根不用继承也可能写出糟糕的程序一样。

但是,当您的问题天生适合使用多继承时,你若只使用单继承或不用继承就会导致维护困难。基本上,当你需要多继承时,要么使用它,要么就得编写一大堆辅助函数。相同的情况也适用于单继承。

在TCPL第三版中大约有十多处使用了多继承,我并没有花费太多的篇幅,因为它的确很简单。

Java设计者决定仅提供一种残缺形式的多继承。那是他们的选择,而且在他们的世界这种选择可能是明智的,但在C++环境中,对于一些我考虑最多的问题,我更倾向于使用多继承而不选择我了解的任何其他替代方法 — 这类问题往往既要求长期可维护又要求高效。

OMO:我完全同意。Java有对象语义,而C++既有对象又有指针。尽管Java模型更简单,但它扩大了“没有给一个引用配置对象”的错误。我个人认为,尽管递归类型(recursive types)隐藏了指针语义,它仍不失为一种更好的理论研究方式。您怎么看呢?

BS:我想近来指针背上了一个坏名声。理论上,我们或许可以不用指针,但在现实世界的软件中却似乎离不开它。给指针另取个别名并没什么作用。

当你想指向一个元素的时候,指针是最佳结构。我认为,指针的大部分问题源于在较低层级上的滥用 — 例如C风格的字符串,再例如需要程序员直接管理连接关系的链表。C++标准库中的string、容器还有算法在这些地方该会派上用场。低阶的指针管理就会从新手和普通程序员写的多数代码中去除。以我个人观点看,直接使用“指向指针的指针”的任何代码段都存在问题。

OMO:我同意您的说法。尤其有了泛型集合类的辅助,我相信代码里的指针几乎总应以高阶结构取代。Java1.1有一个小型反射包(reflection package)。您是否曾想过给C++加上反射机制?

BS:我常常那样想。可是,我没发现任何方法能让一门语言在直接支持完整反射机制的同时不导致严重的性能开销。另外,反射机制提倡的编程风格像是这样:观察源程序文本难以确定发生了什么,且妨碍静态检查。我视此为一个难题。因此,C++的RTTI机制仅提供了在运行时确定对象类型的最少信息。在必要的时候,此机制可被用以提供更多的类型信息,但任何这样的信息都超出了C++标准的保证范围。

OMO:强静态类型即便处理不了绝大部分情况也能够处理许多情况,对此我完全赞同。我认为“动态类型或动态反射从原理上讲是相当高级的,像其他高级技术一样,若没有动态设施就得用其他替代惯用法(也就不得顾及或少顾及最佳解决方案),若使用它们则可以更轻松地解决问题。但就像任何其他东西那样,动态性也可能被滥用或误用。

我听到的最新消息:30%~40%的计算机科学系采用C++开设第一学期的一门编程语言课。您是否有更新的统计数据呢?您是否知道专业软件开发社团中使用C++的占多大比重?我猜想这与微软的操作系统或Intel的CPU的统治地位不无关系。

BS:我不知道C++程序员的人数,我也不知道程序员的总人数,但没错,C++在大型系统构建工具中似乎占据一个非常显著的地位,但在小型应用开发工具中的地位却相反。鉴于这种显著差异,“教授C++以及它良好支持的技术”既是一个机会也是一种义务。C++经常被严重地以次优方式使用。以C++语法编写C或Smalltalk风格的代码并不能比用其他语言改进多少。

因此,恰当的C++教学就尤为重要。不同的程序员需要不同的学习方式。例如,一个没任何编程经验的人,与一个试图在已有技能上添加新技术的C程序员,两者需要学习方式截然不同;而一个C程序员又与一个有Pascal或Ada背景的人需要的学习方式有区别。

但不论哪种情况,我都鼓励通过一种强调“强静态类型和抽象技术”的方式学习C++。我认为不宜过早过重地强调C的内容或“类继承层次”。从接触“强静态类型检查”和“具体类和抽象类”,到迈向“C与C++的公共子集中的诡异部分”或“面向对象编程的诡异部分”,两者间尚有很长一段路程。

OMO:Mike Spertus就这个问题写过一篇文章,认为用C++的一个子集编写Java代码就可以很容易地翻译成Java代码,如此一来代码就可移植并且能让那些要求用C++编写代码的老板满意。更进一步,(Mike在以前的Object Currents专栏写过)一个观点认为,无论如何,编写应用程序都应使用简单的语言结构,而构建工具和库时再用那些更复杂的东西(比如运算符重载),这样就能避免应用程序晦涩难懂。您对此有何看法?Mike还认为,由于“垃圾回收”备选工具包已具有强大的开发成熟度和灵活性,C++中用了会更好。您同意他的说法吗?

BS:唔。在我看来,C++是一门最适合实现垃圾回收的语言,但是对于垃圾回收式C++我还没有积累足够的个人经验以便提供详细的建议。如果你想要一个C++垃圾回收器,有很多不错的选择 — 既有免费的,也有商业支持的。

C++实现垃圾回收是高效的,因为与那些传统的垃圾回收式语言“将所有东西都在分配在堆中”的做法(比如Lisp、Smalltalk和Java)相比,C++合乎语言习惯,需要垃圾回收的情况要少得多。C++的垃圾回收器还有另一项优势:它能够处理程序中C语言部分产生的垃圾。

还要记住,标准库容器是负责其元素的内存管理的。这意味着即便没有垃圾回收器,你需要显式执行的内存管理操作数量也会被大大减少。

我认为相对缺乏经验的C++程序员显然需要尽力避免使用语言的诡异部分。但是,大多数程序员都没任何理由被吓得连语言的大部分内容都不敢使用了。例如,倘若多加小心,操作符重载是相当简单且有用的。但这并不是说“编写一个矩阵代数库”是第一个C++项目的好选择。在那个领域,找一个可用的矩阵库并集中精力学好如何使用它才是明智的选择。

不过,把自己局限在“C++的C子集”或“C++之类似Java的子集”对于多数程序员来说是一个坏主意。对于初学者而言,除非你使用模板,否则你只能写出类型安全性很差的代码。一个程序(在一些界定良好的小范围之外)出现“转型操作”(显式类型转换)是设计低劣的一种迹象。多数应用代码只需要少数的“转型”,而那些强迫用户使用“转型”的库是因为它们没能利用现代C++的优势。当一种语言机制适合解决一个问题时,若不用之只会迫使本来可以由它控制的复杂性重现于用户代码中。

OMO:精彩的观点,对此我曾做过相同的论述,合适地使用复杂特性可以简化编程并且能够避免“Turing Tarpit”,这似乎与多继承问题(也是我反思的问题)一样。

BS:C++是一门可以伴你成长的语言。我不认为“你不可能在一周或一月内掌握它及其关键技术”此一事实可以作为抱怨的理由。多数复杂内容的存在,是为了当你需要它们时能让你的生活更简单。重要的是,C++可以分阶段学习,绝大多数你不需要的内容不会影响你的学习。

D&E是我对“C++是什么以及为什么会那样”的解释。第三版TCPL是我目前“展示C++如何学习如何使用”的最佳尝试,它“高瞻远瞩”了它所依赖的基础,并解释了标准C++中那些最近才可用的特性。我认为更好的东西还会出现。

参考资源

1. Stroustrup, Bjarne, The C++ Programming Language, Third Edition, Addison-Wesley, Reading, MA, 1997.

2. Stroustrup, Bjarne, The Design and Evolution of C++, Addison-Wesley, Reading, MA, 1994.

3. Parallel Programming Using C++, Gregory V. Wilson and Paul Lu (editors), The MIT Press, Cambridge, MA, 1996.