《C++ 语言的设计和演化》摘要暨读后感

序:
许多事实给了我们一种警示:时尚转眼就可能变成为无人理睬的烂泥,仅仅被眼球注意的东西很快就会被忽视,炒作最凶的东西往往也消失得最快,而真正有价值的成果则往往起源于人们最基本的需求和向往。

 

致读者:
在此我要重申自己长期的且强烈持有的一个观点:语言的比较很少是有意义的、更少是公平的。

 

我始终不渝的信念是,所有成功的语言都是逐渐成长起来的,而不是仅根据某个第一原则设计出来的。原则是第一个设计的基础,也指导着语言的进一步演化。但无论如何,即使原则本身也同样是会发展的。

 

第一部分(C++的由来和发展、回顾与展望——thy)
第一章 C++的史前时代:

一种程序设计语言可能成为程序员日常生活中最重要的一个因素。但是无论如何,一个程序设计语言只是这个世界中微乎其微的一个部分,因此也不应该把它看得太重了。要保持一种平衡的心态,特别重要的是应该维持自己的幽默感。

 

第二章 带类的C:

这一点就是后来成长为C++设计的一条经验法则的初始概念,这个法则是:用户定义类型和内部类型与语言法则的关系应该是一样的,能够从语言及其相关工具方面得到同样程序的支持。

 

在这些年里,沿着这条线索的思考逐渐演变成为一条C++设计规则:只提供一个特征是不够的,还必须以一种实际上可以负担得起的形式来提供它。

 

C++的访问控制是为了防止意外事件而不是防止欺骗。任何程序设计语言,只要它支持对原始存储器的访问,就会使数据处于一种开放的状态,使所有有意按照某种违反数据项原本类型规则所述的方式去触动它的企图都能够实行。保护系统的职责就是保证所有违反类型系统的操作都只能显式地进行,并且尽量减少这类操作的必要性。

 

第三章 C++的诞生:

也就是说,正交性应该作为第二位的原则——放在对于有用性和效率的最基本考虑之后。

 

良好设计的关键是对问题的深入认识,而不是提供了多少最高级的特征。

 

“C++是一种通用程序设计语言,其设计就是为了使认真的程序员能够觉得编程序变得更愉快了。”

 

第四章 C++语言设计规则:

理论必须与试验数据相吻合,否则就应被更好的理论取代。

 

C++的一般性规则
         C++的发展必须由实际问题推动。
         不被牵涉到无益的对完美的追求之中:任何程序设计语言都不是完美的,由于问题和系统都在持续的变化之中,将来也不会有完美的语言。
         C++必须现在就是有用的;
         每个特征必须有一种合理的明显实现方式:不应该有必须通过复杂算法才能正确有效实现的特征;
         总提供一条转变的通路;
         C++是一种语言,而不是一个完整的系统;
         为每种应该支持的风格提供全面支持;
         不试图去强迫人做什么。

C++的设计支持规则
         支持一致的设计概念;
         直接说出你的意思:允许用语言本身表达所有重要的东西,而不是在注释里面或者通过宏这类黑客手段;
         所有特征必须是能够负担的;
         允许一个有用的特征比防止各种错误使用更重要:在长期的过程中程序员必然会学习。这种观点也是C语言传统上“相信程序员”口号的一种变形;
         支持从分别开发的部分出发进行软件的组合。

C++的语言的技术性规则
         不隐式地违反静态类型系统;
         为用户定义类型提供与内部类型同样好的支持;
         局部化是好事情;
         避免顺序依赖性;
         如果有疑问,就选择有关特征的那种最容易教给人的形式;
         语法是重要的(常以某些我们不希望的方式起作用);
         应该清除使用预处理程序的必要性。

C++的低级程序设计支持规则
         使用传统的(dumb)连接程序;
         没有无故的与C的不兼容性;
         在C++下面不为更低级的语言留下空间(除汇编语言之外);
         对不用的东西不需要付出代价(0开销规则);
         遇到有疑问的地方就提供手工控制的手段。

 

我对C++的观点是,它是一种生产软件的新语言,特别关注那些影响程序结构的机制,与只做一些小调整的自然倾向相比,这种观点走的完全不是同一条路。

第五章 1985-1993年表:
Release2.0、《带标注的C++参考手册》、ANSI和ISO的标准化

 

第六章 标准化:

实际上人们有一个共识,转变到面向对象的风格也将导致参数表的显著缩短,因为一些往常是参数或者全局的值现在却变成局部状态了。基于这些经验,我预期平均的参数表长度将下降到2以下,而超过两个参数的情况装变得罕见。

 

第七章 关注和使用:

程序设计环境也可以被提供商用于将用户锁定在一个由特征、库、工具和工作模板所封闭的世界里,不能很容易地转到其他系统去。

 

“必须特别当心,应该保证程序源代码能够以很低的代价在不同的这类环境之间转移。”

 

新的概念需要通过实践去学习和掌握。老的反复试验过的工作习惯需要重新评价。

 

如果你能够拿出全部时间学习C++,你就可能更快地适应它。但是,在没有将新思想设计应用到真实的项目之前,这个适应也很可能是骗人的。面向对象的编程和面向对象的设计基本上是实践性训练而不是理论训练。

 

可悲的是,人们常常忘记,实际中永远存在对各种各样语言的需求,需要真正壁龛里的语言,也需要试验性的语言。称赞某种语言,比如说C++,并不意味着批评所有其他的语言。

 

第八章 库:

设计一个库比增加一个语言特征更好,这种情况是经常出现的。

 

设计一个库,实际上经常能成为追求新机制的狂热的一种最具建设性的发泄方式。只有在迈向库的道路真正走不通的情况下,才应该踏上语言扩充之路。

 

在标准I/O流cout、cin等名字里面的c表示字符,它们都是为基于字符的I/O而设计的。

 

第九章 展望:

你无法两次游过同一条河。

 

"C++是一种通用的程序设计语言,其设计就是为了使认真的程序员能觉得编程序变得更愉快。"(作者这里引用他自己的话,足见他对这一设计宗旨的笃信——thy

 

C++使面向对象的程序设计和数据抽象变便宜,可以使用了。

 

我也一直把环境和语言的隔离看成是最根本的东西。我并不希望只使用一个语言、一集工具、或者一个操作系统。为了能提供选择,隔离就是最基本的东西。而一旦有了这种隔离之后,人们就可以提供不同的环境去适应不同的工作和不同的需要,无论是技术支持方面、资源消耗方面,还是可移植性方面。


C++是为严肃认真的程序员设计的,它也将为能帮助他们面对更大更复杂的工作而发展成长。
 

“按照我们的评价,C++已经是太大太复杂了,有成百万行的代码已经放在那里,我们需要努力不去打破它们。...... 只要可能,我们将更愿意看到以程序设计技术或者库函数代替语言的扩充。”

 

我构造C++是想作为一座桥梁,程序员能够借助于它,从传统的程序设计过渡到依赖于是数据抽象和面向对象的程序设计。在一个很长的时期里我们还需要这座桥梁

 

C++的长处,更多地在于它对许多问题都是很好的解决途径,而不在于对某个特定问题是最好的解决途径。

 

C++最显著的强项,就在于它能够在组合了多种不同应用的各个方面的系统或者组织里很好地工作。

 

所有的语言都要死亡,或者将为迎接新的挑战而改变。一个有着极大的而又活跃的用户社团的语言将总是去改变而不是死亡。这也就是发生在C语言上的事情,由此产生了C++。而到某一天,这件事也可能发生在C++身上。


C++并不完美;它没有想设计成为完美的东西,任何其他能用语言也不可能。

 

从根本上说,发展并不是来自某个孤立的进步,而是来自在不同领域中的大量各种各样的进步。

 

第二部分(C++的语言特征)
第十章 存储管理:

(thy整理—)用户在以下三种情况下可能需要对于存储分配和释放的细粒度控制:
一是对某个频繁使用的类(如树结点、链表的链接、点、线、消息等)做一个独立的类分配器。
这里有两个因素在起作用:能用存储分配操作的运行时间和存储开销,以及由于各种大小的对象混合而产生的碎片问题。

 

二是那种需要在资源非常紧张的环境里运行很长很长时间而又不能中断的程序。


三是某个对象必须放到某个特定的地址,或者放到某块特殊的存储区域里,以满足硬件或者系统的特殊要求。

 

第十一章 重载

这个规则(仅在没有其他指针参数能够匹配时重载才会选中void*参数)还有一个有趣的性质:它将void*确立为类转换树的根。

 

一个更简单、更严格、更容易理解的语言除了能吸引那些对现存语言一直不满的程序员外,还必须能够吸引更多的敢于冒险的程序员。

 

私用的析构函数也能制止派生类(实际上私用的构造函数也能制止派生)。这实际上说明,带有私用析构函数的类与抽象类在逻辑上互为补集。

 

第十二章 多重继承

除了只在派生类里提供一个对象外,virtual基类在其它方面和非虚基类是完全一样的。

 

但不管怎样,通过虚函数访问的类和只简单保存几个数据项的类通常是最好的虚基类。

 

语言的战争多半都有点蠢,而集中在一个孤立的特征上就更愚蠢了。

 

“多重继承就像是一顶降落伞,你并不经常需要它,但是在你需要的时候它就是最关键的了。”(——Grady Booch)

 

第十三章 类概念的精炼

一个抽象类表示了一个界面。

 

一个抽象类就是一个纯粹的界面,对应的实现是通过由它派生的类提供的。

 

我很看重能够分阶段定义类的能力;也就是说,我发现预先定义一些纯虚函数,并把另外一些留给进一步的派生类去定义也是很有用的。

(const的)获益主要还是在代码的清晰性、能够预先计算出值因此可以放进ROM的对象数量的增加、代码的分段特性等等。


人们还是在不断地将各种没有必要的东西装入他们的头文件,从而受到过长编译时间的伤害。因此每一种能够帮助减少用户和实现者之间不必要的耦合的技术都是非常重要的。(如类的前向声明、使用抽象界面设计以使得只需导入抽象类头文件、使用如<iosfwd>这样的前向引用模板类头文件)

 

第十四章 强制

我始终不认为以类型开关语句的方式去组织程序应该得到直接支持。

 

一种简单的转换策略就是对所有强制都用static_cast,然后再看编译程序会说些什么。

第十五章 模板

在我的心里,模板和异常是一个硬币的两面:... ...

 

类型或算法的任何性质都可以用一个类型表示,...,这样的类型就可以用于指导重载的解析,通过它们把依赖于有关性质的函数选出来。

 

一个专门化必须在使用之前就已经声明。例如:

"C++是一个足够强有力的语言——在我们的经验中第一个这样的语言——它使人能构造出类属的程序设计部件,在其中结合了数学的精确、美丽和抽象性,再加上非类属的手工编制代码的效率。"(——Alex Stepanov)

 

我关于容错系统的观点是:这种系统必须是多层次的,......,到了某一点,一个单元就必须放弃,而将进一步的清理工作留给“更高层次”的单元。

 

要想提供一些功能,使一个单独的程序就能从所有错误中恢复,这完全是一种误导,也会使错误处理策略变得非常复杂,其本身就会成为新的错误根源。

 

异常处理设计的核心点实际上是资源的管理。

 

因此我们可以将资源的请求和释放问题适当地用一个带有建构函数和析构函数的类的对象来处理。......在任何情况下,(此对象)都将在自己的作用域结束处被销毁,它的析构函数将释放相关的资源。......我把这种技术称作“资源获取即初始化”。

 

(如果)在建构函数里出错,......,异常处理提供了一种具有普遍性的解决办法:

更重要的是,C++异常处理机制能保证部分构造起来的对象也正确地销毁,即将那部分已经构造完成的子对象销毁,而那部分还没有构造的子对象就不做。

 

void f() throw (e1, e2) {} 其优点不仅在于节省了类型检查,最重要的优点是,函数声明属于用户可以看见的界面。

 

C++异常处理机制......使不抛出异常的程序不付出任何时间代价。

 

异常处理并没有在任何实际程度上影响对象的布局模型。

 

******************************************************************************************************************************************************

书中作者设计一门综合性程序设计语言的哲学对我很有启发,正如《The Pragmatic Programmer》所说,不要去追求完美,因为没有完美。(追求完美才是完美的——thy

 

记得我刚刚学编程时,成天去网上看大家的讨论,是C++好,还是Objective Pascal好,是VC好还是BCB好。。。现在觉得这种比较既是对的也是错的。错是因为追求不存在的完美,对是因为对于一种抱着某种目的的人(实现某个功能、学习某个领域。。。),他必须找到这个领域的“完美”的语言,少走弯路。

 

作者作为C++的设计者、大宗师,在书中所散发出的学者气质、绅士风度、研究人员敏锐的目光、思想者超前的眼光,这些都深深折服了我。
以我的层次,书中的内容也只能领悟30%,以上摘要的都是我能看懂的,但这已经让我获益非浅了。以后有机会再来拜读大师的经典吧。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值