C++

发展历史

C++语言发展大概可以分为三个阶段：第一阶段从80年代到1995年。这一阶段C++语言基本上是传统类型上的面向对象语言，并且凭借着接近C语言的效率，在工业界使用的开发语言中占据了相当大份额；第二阶段从1995年到2000年，这一阶段由于标准模板库（STL）和后来的Boost等程序库的出现，泛型程序设计在C++中占据了越来越多的比重。当然，同时由于Java、C#等语言的出现和硬件价格的大规模下降，C++受到了一定的冲击；第三阶段从2000年至今，由于以Loki、MPL(Boost)等程序库为代表的产生式编程和模板元编程的出现，C++出现了发展历史上又一个新的高峰，这些新技术的出现以及和原有技术的融合，使C++已经成为当今主流程序设计语言中最复杂的一员。
比雅尼·斯特劳斯特鲁普（Stroustrup）工作起于1979年的C with Classes。这个构思起源于斯特劳斯特鲁普做博士论文时的一些程序撰写经验。他发现Simula具备很利于大型软件开发的特点，但Simula的运行速度太慢，无法对现实需求发挥功效；BCPL虽快得多，但它过于低级的特性，使其不适于大型软件的开发。当斯特劳斯特鲁普开始在贝尔实验室工作时，他有分析UNIX核心关于分布式计算的问题。回想起他的博士论文经验，斯特劳斯特鲁普开始为C语言增强一些类似Simula的特点。之所以选择C，是因为它适于各种用途、快速和可移植性。除了C和Simula之外，同时也从其它语言中获取灵感，如ALGOL 68、Ada、CLU以及ML。
刚开始时，类别、派生类、存储类型检查、内联和缺省参数特性，都是透过Cfront引入C语言之中。
1983年，C with Classes改命名为C++（++是C语言中的增值操作符）。加入了新的特性，其中包括虚函数、函数名和运算符重载、参考、常量、用户可控制的自由空间存储区控制、改良的类型检查，以及新的双斜线（//）单行注解风格。
1985年，发布第一版《C++程序设计语言》，提供一个重点的语言参考，至此还不是官方标准。1985年10月出现了第一个商业化发布。
1989年，发布了Release 2.0。引入了多重继承、抽象类别、静态成员函数、常量成员函数，以及成员保护。1990年，出版了The Annotated C++ Reference Manual。这本书后来成为标准化的基础。稍后还引入了模板、异常处理、名字空间、新的强制类型转换，以及布尔类型。
随着C++语言的演变，也逐渐演化出相应的标准程序库。最先加进C++标准库的是流I/O程序库，其用以取代传统的C函数，如printf和scanf。随后所引入的程序库中最重要的便是标准模板库，简称STL。
多年后，一个联合的ANSI-ISO委员会于1998年对C++标准化（ISO/IEC 14882：1998）。在官方发布1998标准的若干年后，委员会处理缺陷报告，并于2003年发布一个C++标准的修正版本。2005年，一份名为Library Technical Report 1（简称TR1）的技术报告发布。虽然还不是官方标准的一部分，不过它所提供的几个扩展可望成为下一版C++标准的一部分。几乎所有当前仍在维护的C++编译器皆已支持TR1。
当前最新的C++标准是2017年12月发布的ISO/IEC 14882:2017，又称C++17或C++1z。
虽然C++免专利，但标准文件本身并不是免费的，尽管标准文档不是免费的，但是很容易从网络中获取，最简单的就是C++标准文档之前的最后一次草稿版本，它与标准的差别几乎只在于排版上。

C++名字的由来

C++这个名字是Rick Mascitti于1983年中所建议的，并于1983年12月首次使用。更早以前，尚在研究阶段的发展中语言曾被称为“new C”，之后是“C with Classes”。在计算机科学中，C++仍被称为C语言的上层结构。它最后得名于C语言中的“++”运算符（其对变量的值进行递增）。而且在共同的命名约定中，使用“+”以表示增强的程序。斯特劳斯特鲁普说：“这个名字象征着源自于C语言变化的自然演进”。C+是一个和C/C++无关的早期编程语言。
Rick Mascitti在1992年被非正式地问起名字的由来，他表示这是在半开玩笑中说出的。他从没想过C++会成为这门语言的正式名字。
有一个关于C++名字的笑话是，当你使用后缀++时，附加只发生在运算之后（因此，它应该是++C，而不是C++，这个笑话是说时下某些程序员还在以使用C的方式使用C++，这通常被一些权威著作认为是不正确的）。

标准程序库

1998的C++标准分为两个部分：核心语言和C++标准程序库；后者包含了大部分标准模板库和C标准程序库的稍加修改版本。存在许多不属于标准部分的C++程序库，且使用外部链接，程序库甚至可以用C撰写。
C++标准程序库充分吸收了C标准程序库，并佐以少许的修改，使其与C++良好的运作。另一个大型的程序库部分，是以标准模板库（STL）为基础，STL于1994年2月正式成为ANSI/ISO C++。它提供了实用的工具，如容器类（如：Array和Vector），迭代器（广义指针）提供容器以类似数组的访问方式，以及泛型算法进行搜索和排序的运算。此外还提供了(multi)map和(multi)set，它们都共享相似的成员函数。因此，以下成为可能，使用模板撰写泛型算法，它可以和任何容器或在任何以迭代器定义的序列上运作。如同C，使用#include指令包含标准表头，即可访问程序库里的功能。C++提供69个标准表头，其中19个不再赞成使用。
使用标准模板库（例如：使用std::vector或std::string来取代C风格的数组或字符数组）有助于导向更安全和更灵活的软件。
在STL在纳入C++标准以前，是来自HP和后来的SGI的第三方程式库，标准中并未称之为“STL”，它只是标准库中的一部分，但仍有许多人使用这个名称，以别于其它的标准库（输入／输出流、国际化、诊断、C程序库子集，等等）。
另外，如std::basic_string此类标准委员会添加的接口，有时也被误认为STL；实际上它们并不存在于原始的SGI STL中，在标准化后SGI STL才从标准库吸收加入其中。

C++中的特色

和C语言相比，C++引入了更多的特性，包括：复合类型（引用类型等）、const限定符和constexpr常量表达式、类型处理运算符（类型别名及auto和decltype等多种类型指示符）、C++标准库（IO库与多种容器类）与迭代器、动态内存与智能指针、函数重载、面向对象程序设计（如数据抽象、成员函数、类作用域、构造函数与析构函数、静态成员、访问控制与继承、虚函数、抽象类与接口等）、拷贝控制、运算符重载、造型与函数风格的强制类型转换、模板与泛型编程，以及异常处理、名字空间、多继承与虚继承、运行时类型识别及嵌套类等。
和普遍认为的相反，C++不是第一个正式引入const关键字的语言。80年代早期，Bjarne Stroustrup和Dennis Retchie讨论之后提供了在C语言中readonly/writeonly的实现机制，并在带类的C中获取了一定经验。关键字const正式引入C语言是在ANSI C89。这早于第一个C++国际标准近十年，但此时const已被C++实现普遍采用。
C++在某些案例中（见下“与C不兼容之处”），进行比C还要多的类型检查。
以“//”起始作为注解起源自C的前身BCPL，而后被重新引入到C++。
C++的一些特性，C不久之后也采用了，包括在for循环的括号中声明，C++风格的注解（使用//符号，和inline，虽然C99定义的inline关键字与C++的定义不兼容。不过，C99也引入了不存在于C++的特性，如：可变参数宏，和以数组作为参数的较佳处理；某些C++编译器可能实现若干特性，以作为扩展，但其余部分并不符合现存的C++特性）
一个常见的混淆其实只是一个微妙的术语问题：由于它的演化来自C，在C++中的术语对象和C语言一样是意味着存储器区域，而不是类的实体，在其它绝大多数的面向对象语言也是如此。举例来说，在C和C++中，语句int i;定义一个int类型的对象，这就是变量的值i将在指派时，所存入的存储器区域。

C++语言中的const关键字

const是一个C和C++语言的关键字，意思是宣告一个常量(不能改变的变量)，即只读。使用const在一定程度上可以提高程序的安全性和可靠性，也便于实现对此进行优化（如把只读对象放入ROM中）。const作为类型限定符，是类型的一部分。
以下是和C语言兼容的用法：
1 int m = 1, n = 2;   // int 类型的对象2 const int a = 3;    // const int 类型的对象3 int const b = 4;    //同上4 const int *p        //指向 const int 类型对象的指针5 int const *q;       //同上6 int *const x;       //指向 int 类型对象的const 指针；注意 const 的位置7 const int *const r; //指向 const int 类型对象的const 指针8 int const *const t; //同上
但是，const在C++中有更强大的特性。它允许在编译时确定作为真正的常量表达式。例如，
1 const int max_len = 42;2 int a[max_len];
此前C语言并不支持这样的用法，直到C99允许用变量作为数组长度（需要注意的是C99中的VLA支持运行期确定数组长度，但C++从未支持）。此外，C++中，名字空间作用域的const对象的名称隐含内部链接。这意味着直接在头文件里定义const对象被多个源文件包含时，也不会重定义。
在C++11及之后的C++标准中，推荐使用拥有更严格语义的constexpr限定符来表示一个可以出现在常量表达式中的变量。const可区分为顶层const(top-level const)和底层const(low-level const)。
实际上，在语义表达方面，const更多表示为“只读”，constexpr才表示编译期常量。

与C不兼容之处

C++有时被认为是C的超集（superset），但这并不严谨。
各个版本的ISO/IEC 14882的附录C中都指出了C++和ISO C的一些不兼容之处。
大部分的C代码可以很轻易的在C++中正确编译，但仍有少数差异，导致某些有效的C代码在C++中失效，或者在C++中有不同的行为。
最常见的差异之一是，C允许从void*隐式转换到其它的指标类型，但C++不允许。下列是有效的C代码：
1 // 从void *隐式转换为int *2 int *i = malloc(sizeof(int) * 5);
但要使其在C和C++两者皆能运作，就需要使用显式转换：
1 int *i = (int *)malloc(sizeof(int) * 5);
另一个常见的可移植问题是，C++定义了很多的新关键字，如new和class，它们在C程序中，是可以作为识别字（例：变量名）的。
C99去除了一些不兼容之处，也新增了一些C++的特性，如//注释，以及在代码中混合使用。不过C99也纳入几个和C++冲突的新特性（如：可变长数组、原生复数类型和复合逐字常数），而C++11已经加入了兼容C99预处理器的特性。
由于C++函数和C函数通常具有不同的名字修饰和调用约定，所有在C++中调用的C函数，须放在extern "C" { /* C函数声明*/ }之内。

C++的Hello World程序

下面这个程序显示“Hello, world!”然后结束运行：
1 #include <iostream>2 int main() {3     std::cout << "Hello, world!" << std::endl;4     return 0;5 }
这里也可以使用using指令以避免再次声明std::——
1 #include <iostream>2 using namespace std;3 int main() {4     cout << "Hello, world!" << endl;5     return 0;6 }
你可以用“\n”代替以上代码里的“endl”，不过必须用在句子的后端。请不要把斜杠（/）和反斜杠（\）混淆。
1 std::cout << "Hello, world!\n";
但需要知道的是， std::endl 不仅仅会在某个输出流中插入换行字符，还将执行输出流的flush() 函数（即刷新缓冲区），而'\n'则不会。

根据ISO C++的规定，全局main函数必须返回int。
以下两种形式是合法的：
1 int main() {2     // ...3 }
1 int main(int argc, char *argv[]) {2     // ...3 }
不过，在一些编译器（例如Visual C++）上，
1 void main() {2     // ...3 }
也是合法的。永远不要这样写，因为这样的写法没有兼容性。

预处理器

C++主要有三个编译阶段：预处理、转译成目标代码和链接（最后的两个阶段一般才视为真正的“编译”）。在第一阶段，预处理，会将预处理器指令替换成源代码，然后送到下一个编译阶段。

模板

模板（Template）指C++编程语言中的函数模板（function template）与类别模板（class template），这种观念是取材自Simula的泛型程序设计。它采用typename和class两个关键字，来标识模板类别的类型参数。C++11和C++14分别引入了类型别名模板和变量模板。

类别与对象

在面向对象对象程序设计术语中，对象（object）是数据（data）和处理数据的指令（instructions）的联合（association）。模拟（simulate）实际世界（real-world），对象有三种特质（characteristics）：状态（State）、行为（Behavior）、同一性身份，并且使用消息（message）来引发彼此的交互。类别（class）为对象的蓝图或工厂，定义了对象的抽象特质，包括对象的属性特质和对象的行为特质，属性的值即是对象的状态，行为即是对象能够做的事。
C++为类别构成式面向对象编程语言（class-based object-oriented programming language），类别概念具现化（reification）地作为二等公民（second-class citizen）出现在C++语言当中，在语法中明确地使用类别来做到数据抽象、封装、模块化、继承、子类型多态、对象状态的自动初始化。C++中，一个类别即为一个类型，加上封装，一个类别即为一个抽象数据类型（Abstract Data Type，ADT），继承、多态、模板都加强了类别的可抽象性。在C++可以使用class或struct这两个关键字宣告类别（class），而使用new运算符实体化类别产生的实体（instance）即为对象，是一等公民。C/C++以数据成员（data member）表达属性，以成员函数（member function）表达行为。
声明一个Car class：
1 class Car {2 private:3     int isRunning;4 public:5     Run();6 };
但是仍然需要注意，严格来说，C++中对象的概念和C的对应概念接近，表示的是具有特定类型的存储，而非面向对象意义上的“对象”：一个对象不一定是类类型的。此外，C++意义上的“实例”仅指模板实例化的结果，而并不指对象。作为对比，Java的“对象”和“实例”的概念和这里的使用一致。

分析和处理C++原始代码

C/Java/C#都可以用某种LR 剖析器（或其变形）分析文法，但C++是个著名的例外：请看下面的代码。
1 #include <vector>2 #include <string>3 std::vector< std::vector<std::string> >table1;4 std::vector<std::vector<std::string>>table2;
上面的table1显然是一个字符串的二维数组，而table2则未必能通过编译：如果严格遵循LR分析过程，串 >> 会被解释为右移运算符而非两个代表模板参数表结束的右尖括号，因此出现编译错误，必须以table1的方式用空格区分。(在C++11发布之后，特别规定了当处理模板时，>>被优先视为两个>，所以table1和table2均可通过编译.)