第一章 使自己习惯于 C++无论你的编程背景如何,对于 C++ 可能多少有些不习惯。这是一个有着极其丰富特性的威力强大的语言。但是在你能发挥它的威力并有效地使用这些特性之前,你必须使自己习惯于以 C++ 的方式做事。这本书讲的就是如何做到这一点,其中一些内容比其他内容更加基础,本章就讲述这些最基本的内容。
Item 1: 将 C++ 视为语言的联合体
最初,C++ 仅仅是在C的基础上附加了一些面向对象的特性。C++ 最初的名称——“C with Classes”就非常直观地表现了这一点。
作为一个语言的成熟过程,C++的成长大胆而充满冒险,它吸收的观点,特性,以至于编程策略与 C with Classes 越来越不同。异常要求不同的建构功能的途径(参见 Item 29),模板将设计思想提升到新的高度(参见 Item 41),而 STL 定义了一条前所未见的通向扩展性的道路。
今天的 C++ 已经成为一个多范式的编程语言,一个囊括了过程化,面向对象,函数化,泛型以及元编程特性的联合体。这些能力和弹性使 C++ 成为无可匹敌的工具,但也引起了一些混乱。所有的“惯用法”规则似乎都有例外。我们该如何认识这样一个语言?
最简单的方法是不要将 C++ 视为一个单一的语言,而是一个亲族的语言的联合体。在每一个特定的子语言中,它的特性趋向于直截了当,简单易记。但你从一个子语言转到另外一个,它的规则也许会发生变化。为了感受 C++,你必须将它的主要的子语言组织到一起。幸运的是,它只有4个:
C——归根结底,C++ 依然是基于 C 的。模块,语句,预处理器,内建数据类型,数组,指针等等,全都来自于 C。在很多方面。C++ 提出了比相应的 C 版本更高级的解决问题的方法(例如,参见 Item 2(选择预处理器)和13(使用对象管理资源)),但是,当你发现你自己工作在 C++ 的 C 部分时,高效编程的规则表现为 C 的诸多限制范围:没有模板,没有异常,没有重载等等。
面向对象 C++——C++ 的这部分就是 C with Classes 涉及到的全部:类(包括构造函数和析构函数),封装,继承,多态,虚函数(动态绑定)等。C++ 的这一部分直接适用于面向对象设计的经典规则。
模板 C++——这是 C++ 的泛型编程部分,大多数程序员对此都缺乏经验。模板的考虑为遍及 C++ 的,普通的操作提供了好的编程规则,这些包含在特殊的纯模板的部分(此处译文经多次推敲,恐有不确,原文附上,请大家指正:Template considerations pervade C++, and it's not uncommon for rules of good programming to include special template-only clauses)(参见 Item 46通过调用模板函数简化类型转换)。实际上,模板极为强大,它提供了一种全新的编程模式——模板元编程(TMP)。Item 48提供了一个 TMP 的概述,但是,除非你是一个死心塌地的模板瘾君子,否则你不需在此费心,TMP 的规则对主流的 C++ 编程少有影响。
STL——STL 是一个模板库,一个非常特殊的模板库。它将容器,迭代器,算法和函数对象非常优雅地整合在一起,但是。模板和库也可以围绕其它的想法建立起来。STL有很多独特的处事方法,当你和 STL 一起工作,你需要遵循它的规则。
在头脑中保持这四种子语言,当你从一种子语言转到另一种时,为了高效编程你需要改变你的策略,不要吃惊你遭遇到的情景。例如,使用内建(类 C 的)类型时,传值通常比传引用更高效,但是当你从 C++ 的 C 部分转到 C++ 的面向对象部分,用户自定义构造函数和析构函数意味着,通常情况下,更好的做法是将引用传递给 const 参数。在模板 C++ 中工作时,这一点更加重要,因为,在这种情况下,你甚至不知道你的操作涉及到的对象的类型。当你进入 STL,无论如何,你知道迭代器和函数对象以 C 的指针为原型,对于 STL 中的迭代器和函数对象,古老的 C 中的传值规则又重新生效。(关于选择参数传递方式的全部细节,参见 Item 20。)
C++ 不是使用一套规则的单一语言,而是四种子语言的联合体,每一种都有各自的规则。在头脑中保持这些子语言,你会发现对 C++ 的理解会容易得多。
Things to Remember
高效 C++ 编程规则的变化,依赖于你使用 C++ 的哪一个部分。