C++之父谈C++语言设计规则( 八 )


避免顺序依赖性:顺序依赖性很容易使人感到困惑 , 在重新组织代码时也容易引进错误 。 人们都会注意到 , 语句将按定义的顺序执行 , 但却往往会忽视全局声明之间和类成员声明之间的相互依赖性 。 重载规则(11.2节)和基类的使用规则(12.2节)都经过了特殊处理 , 避免其中出现对顺序的依赖性 。 理想情况是 , 如果交换两个声明的顺序会导致另一种不同的意思 , 那么这就应该是一个错误 。 对于类成员的规则就是这样(6.3.1节) 。 但是 , 对全局声明不可能做到这一点 。 C预处理程序可以通过宏处理引进根本无法预期的病态依赖性 , 从而可能造成很大的破坏(18.1节) 。
我在某个时候曾经表达过有关避免微妙的解析方式的愿望 , 说:“帮助你下决心不应该是编译器的事情” 。 换句话说 , 产生编译错误将比产生某种含糊的解析更容易接受 。 多重继承的歧义性规则是这方面的好例子(12.2节) 。 关于重载函数的歧义性规则是另一个例子 , 它也说明了在兼容性和灵活性的约束下 , 要做好这件事有多么困难(11.2.2节) 。
如果有疑问 , 就选择该特征的最容易说清楚的形式:这是在不同可能性之中做选择的第二规则 , 使用起来很有技巧性 , 因为它有可能变成一种关于逻辑美的争论 , 而且可能与熟悉不熟悉有关 。 写出描述它的辅导材料和参考手册 , 看看人们是否容易理解 , 是这个规则的一种实践方式 。 这里的一个意图就是简化教学人员和维护人员的工作 。 还应该记住 , 程序员们不笨 , 不应该通过付出重要的功能方面的代价去换取简单性 。
语法是重要的(常以某些我们不希望的方式起作用):保证类型系统的一致性 , 一般而言 , 保证语言的语义清晰、定义良好 , 是最基本的东西 。 语法是第二位的 , 而且 , 看起来人们能学会去喜爱任何语法形式 。
当然 , 语法就是人们看到的东西 , 也是语言最基本的用户接口 。 人们喜爱某些形式的语法 , 并以某种奇特的狂热去表达他们的意见 。 我认为 , 想改变这些东西 , 或者不顾人们对某些特定语法的对抗情绪去引进新的语义或设计思想 , 都是没希望成功的 。 因此 , C++ 的语法 , 在设法使其更合理和规范的同时 , 也尽可能避免去触犯程序员们的成见 。 我的目标是逐渐使一些讨厌的东西淡出 , 例如隐含的int(2.8.1节)和老风格的强制(14.3.1节)等 , 同时又尽可能地减少使用更复杂形式的声明符语法(2.8.1节) 。
我的经验是 , 人们往往过分热衷于通过关键词来引进新概念 , 以至于如果一个概念没有自己的关键词 , 教起来就非常困难 。 这种作用是很重要的、根深蒂固的 , 远远超过人们口头上表述的对新关键词的反感 。 如果给他们一点时间去考虑并做出选择 , 人们无疑地会选择新的关键词 , 而不是某种聪明的迂回方案 。
我试着把重要操作做成很容易看见的东西 。 例如 , 老风格强制的一个重要问题是它们几乎不可见 。 此外 , 我也喜欢把语义上丑陋的操作在语法上也弄成丑陋的 , 与语义相匹配 , 例如病态的类型强制(14.3.3节) 。 一般说 , 也应该避免过分啰嗦 。
清除使用预处理程序的必要性:如果没有C预处理程序 , C语言本身和后来的C++ 可能早就是死胎了 。 没有Cpp , 它们根本就不能有足够的表达能力和灵活性 , 不能处理重要项目中所需要完成的各种任务 。 但在另一方面 , Cpp丑陋低级的语义也使构造和使用更高级、更优雅的C程序设计环境变得过分困难、代价过分昂贵 。
因此 , 必须针对Cpp的每个基本特征 , 找到符合C++ 语法和语义的替代品 。 如果这个工作能够完成 , 我们就可能得到一个更便宜的大大改进的C++ 程序设计环境 。 沿着这个方向 , 我们也将清除许多很难对付的错误的根源 。 模板(第15章)、inline函数(2.4.1节)、const(3.8节)和名字空间(第17章)都是在这个方向上留下的脚印 。