第1章 绪论
欢迎使用本书!通过阅读本章,您将迈出成为高级C++程序员的第一步。
在本章中,您将学习:
• 为何C++是软件开发的标准;
• 输入、编译和链接第一个C++程序;
• C++11新增的功能。
1.1 C++简史
编程语言旨在让人更容易使用计算资源。C++并非一种新语言,但仍被广泛采用,并在不断改进。2011年,最新的C++标准获得了ISO标准委员会的批准,名为C++11。
C++最初由Bjarne Stroustroup于 1979年在贝尔实验室开发,被设计为C语言的继任者。C语言是一种过程型语言,程序员使用它定义执行特定操作的函数,而 C++是一种面向对象的语言,实现了继承、抽象、多态和封装等概念。C++支持类,而类包含成员数据以及操作数据的成员方法(方法类似于C语言中的函数)。其结果是,程序员需要考虑数据以及要用它们来做什么。一直以来,C++编译器都支持C语言,这具有向后与既有代码兼容的优势,但也存在缺点,那就是编译器非常复杂,因为随着C++的发展,编译器既要实现所有的新功能,又要向程序员提供这种向后兼容的功能。
C++是一种中级编程语言,这意味着使用它既可以高级编程方式编写应用程序,又可以低级编程方式编写与硬件紧密协作的库。在很多程序员看来,C++既是一种高级语言,让他们能够开发复杂的应用程序,又提供了极大的灵活性,让开发人员能够控制资源的使用和可用性,从而最大限度地提高性能。
虽然有更新的编程语言面世,如Java以及其他基于.NET的语言,但C++始终深受欢迎并在不断发展。较新的语言因提供了某些功能(如通过垃圾收集管理内存)让一些程序员钟爱有加,但在需要精确控制应用程序的性能时,他们还是会选择C++。当前,常常使用C++编写Web服务器,并使用HTML、Java或.NET编写前端应用程序。
经过多年的发展,C++得到了广泛接受和采纳,但存在多种不同版本,因为有很多不同的编译器,它们风格各异。鉴于 C++广受欢迎,且不同的版本之间存在差异,这导致了众多互操作性和移植方面的问题,需要对其进行标准化。
1998年,第一个C++标准获得了 ISO标准委员会的批准,这就是 ISO/IEC 14882:1998。2003年进行了修订,即为 ISO/IEC 14882:2003。最新的 C++标准于 2011年 8月获批,其官方名称为 C++11 (ISO/IEC 14882:2011),它包含一些雄心勃勃的改进。
网上的很多文档仍称这个C++标准为C++0x。人们最初预期新标准将于2008或2009年获批,因此用x表示获批的年份。但提议的新标准到2011年才获批,因此将其称为C++11。换句话说,C++11是新的C++0x。
无论你是什么人,做什么工作(无论是经验丰富的程序员,还是将计算机用于特定目的的人),都可能经常会用到 C++应用程序和库。C++常用于开发操作系统、设备驱动程序、办公软件、Web 服务器、基于云的应用程序和搜索引擎,甚至用于编写新编程语言编译器。
1.2 编写C++应用程序
当您在计算机上启动Notepad或VI时,实际上是命令处理器运行该程序的可执行文件。可执行文件是可运行的成品,应按程序员期望的那样做。
要创建可在操作系统中运行的可执行文件,第一步是编写一个C++程序。创建C++应用程序的基本步骤如下。
1.使用文本编辑器编写C++代码。
2.使用C++编译器对代码进行编译,将代码转换为包含在目标文件中的机器语言版本。
3.使用链接程序链接编译器的输出,生成一个可执行文件(如Windows中的.exe文件)。
您在编程时创建的是文本文件,但微处理器无法处理这样的文件。在编译过程中,C++代码(通常包含在.CPP文本文件中)被转换为处理器能够处理的字节码。编译器每次转换一个代码文件,生成一个扩展名为.o或.obj的目标文件,并忽略这个CPP文件可能对其他文件中代码的依赖。解析这些依存关系的工作由链接程序负责。除将各种目标文件组合起来外,链接程序还建立依存关系,如果链接成功,则创建一个可执行文件,供程序员执行和分发。
大多数复杂应用程序很少能够一次通过编译并完美地运行,由众多程序员合作开发的应用程序尤其如此。无论使用什么语言(包括 C++)编写,庞大或复杂的应用程序都需要运行很多次,以分析问题和发现Bug。修复Bug后,重新生成程序,再重复上述过程。因此,除编写、编译和链接等三个步骤外,开发过程通常还包括调试步骤。在这个步骤中,程序员使用工具(如监视点)和调试功能(如逐行执行应用程序)对应用程序中的异常和错误进行分析。
很多程序员都喜欢使用集成开发环境(Integrated Development Environment,IDE)。集成开发环境让您能够在一个统一的用户界面中完成输入、编译和链接步骤,它还提供了调试功能,让您能够更轻松地发现错误并解决问题。
有很多免费的C++ IDE和编译器。在Windows和Linux系统中,最流行的分别是Microsoft Visual C++学习版和GNU C++编译器g++。如果您使用的是Linux系统,要使用g++编译器来开发C++应用程序,可安装免费的Eclipse IDE。
在编写本书时,还没有全面支持C++11标准的编译器,但前述编译器支持C++11的很多主要功能。
了解工具和步骤后,该编写第一个C++应用程序了,它在屏幕上打印Hello World!。
如果您使用的是Windows操作系统和Microsoft Visual C++学习版,可采取如下步骤。
1.选择菜单“文件”>“新建”>“项目”,以新建一个项目。
2.选择类型“Win32控制台应用程序”,并取消选择复选框“预编译头”。
3.将项目命名为Hello,并用程序清单1.1所示的代码替换Hello.cpp中自动生成的内容。
如果您使用的是Linux操作系统,使用简单的文本编辑器(我使用的是Ubuntu上的gedit)创建一个包含程序清单1.1所示内容的CPP文件。
程序清单1.1 Hello Wrold程序(Hello.cpp)
这个应用程序很简单,只是使用std::cout在屏幕上打印一行消息。std::endl命令cout换行。该应用程序退出时向操作系统返回零。
默读程序时,知道特殊字符和关键字的发音可能会有所帮助。
例如,对于#include,可读作 hash-include、sharp-include 或 pound-include,这取决于您以前的背景。
同样,对于std::cout,可读作standard-c-out。
别忘了,魔鬼隐藏在细节中,这意味着您必须准确地输入程序清单中的代码。编译器对代码的要求非常严格;语句必须以;结尾,如果您错误地输入了:,就会陷入一片混乱。
如果您使用的是Microsoft Viusual C++学习版,可在该 IDE中按Ctrl + F5直接运行程序。这将编译、链接并执行应用程序。也可依次执行如下步骤。
1.右击项目并选择“生成”,准备生成可执行文件。
2.在命令提示符中,切换到可执行文件所属的文件夹(通常是项目文件夹中的Debug文件夹)。
3.输入可执行文件的名称以运行它。
在Microsoft Visual C++中编写的程序与图 1.1极其相似。
图1.1 在Visual C++ 2010学习版中创建的简单C++程序“Helo World”
如果您使用的是Linux系统,可使用如下命令行调用g++编译器和链接程序。
该命令行让g++编译C++文件Hello.cpp,并创建一个名为hello的可执行文件。在Linux和Windows系统中,分别执行命令.\hello或Hello.exe,这将返回如下输出。
祝贺您踏上了学习有史以来最流行、最强大的编程语言之一的道路!
C++ ISO标准的意义
正如您看到的,通过遵守标准,可在多种平台(操作系统)中编译和执行程序清单1.1所示的代码——前提条件是有遵守标准的C++编译器。因此,如果要编写让Windows用户和Linux用户都能运行的软件,通过在编程中遵守标准(不使用编译器或平台特有的语义)是一种获取更多用户的简单方式,这让您无需针对要支持的每种环境进行编程。当然,编写不需要在操作系统级进行大量交互的应用程序时,这种方法的效果最佳。
编译器的要求非常苛刻,但优秀的编译器会相当明确地指出错误在什么地方。如果您在编译程序清单1.1所示的应用程序时遇到问题,错误消息将与下面的内容极其相似(这是故意省略第5行末尾的分号导致的错误):
这条错误消息来自Visual C++编译器,对错误进行了详细描述。它指出了包含错误的文件的名称,在哪一行遗漏了分号(这里是第 6 行),还使用错误编号(这里是 C2143)对错误本身进行了描述。在这个例子中,虽然遗漏分号的是第5行,但错误消息却指出错误发生在第6行,这是因为对编译器来说,只有等它返回语句后,才能确定在返回前,前一条语句必须结束。如果您可在第6行开头添加分号,程序将通过编译!
不同于VBScript等语言,在C++中语句分行并不能自动结束语句。
在C++中,一条语句可跨越多行。
1.3 C++11新增的功能
如果您是经验丰富的 C++程序员,可能发现程序清单 1.1 所示的基本程序没有任何变化。虽然C++11可以与以前的C++版本兼容,但仍然做了大量工作让这种语言使用起来更容易。
auto 让您能够定义这样的变量,即编译器将自动推断其类型,这简化了变量声明,同时又不影响类型安全。Lambda函数是没有名称的函数,让您能够编写紧凑的函数对象,而无需提供冗长的类定义,从而极大地减少了代码。C++11让程序员能够编写可移植的多线程C++应用程序,同时确保它们遵守标准。这些应用程序支持并行执行范式,在用户升级到多核CPU以改善硬件配置时,其性能将相应地提升。
本书将讨论C++11所做的众多改进,这里列举的只是其中几项。
1.4 总结
在本章中,您学习了如何编写、编译、链接和执行第一个C++程序。本章还简要地介绍了 C++的发展历程,并演示了如何在不同的操作系统中使用不同的编译器对同一个程序进行编译,从而证明了标准的重要意义。
1.5 问与答
问:可以忽略编译器发出的警告消息吗?
答:在有些情况下,编译器会发出警告消息。警告与错误的不同之处在于,相关代码行的语法是正确的,能够通过编译,但可能有更佳的编写方式。优秀编译器在发出警告的同时提供修复建议。
修复建议可能是一种更安全的编程方式,也可能让应用程序能够处理非拉丁语字符和符号。您应该留意警告,并相应地改进应用程序。除非您确定警告是误报,否则不要对其视而不见。
问:解释型语言与编译型语言有何不同?
答:诸如Windows Script等语言是解释型的,不需要编译。解释型语言使用解释器,解释器直接读取脚本文件(代码)并执行指定的操作。因此,要在计算机上执行脚本,必须安装解释器。在运行阶段,解释器在微处理器和代码之间充当翻译,因此性能通常会受到影响。
问:什么是运行错误?它与编译错误有何不同?
答:执行应用程序时发生的错误称为运行错误。在较旧的Windows版本中,您可能遇到过臭名昭著的“非法访问(Access Violation)”错误,它就是运行错误。最终用户不会遇到编译错误,这种错误表明程序存在语法问题,禁止程序员生成可执行文件。
1.6 作业
作业包括测验和练习,前者帮助读者加深对所学知识的理解,后者提供了使用新学知识的机会。请尽量先完成测验和练习题,然后再对照附录D的答案。在继续学习下一章前,请务必弄懂这些答案。
1.解释器和编译器有何不同?
2.链接器的作用是什么?
3.正常的开发周期包括哪些步骤?
4.C++11标准如何更好地支持多核CPU?
1.阅读下面的程序,在不运行它的情况下猜测其功能。
2.输入练习1中的程序,然后编译并链接它。它的功能是什么?与您的猜测相符吗?
3.下面的程序存在什么样的错误?
4.修复练习3中程序的错误,重新编译、链接并运行它。它的功能是什么?