C++ Primer Plus 知识的讲解

程序模板

#pragma region xxx.cpp
//xxx.cpp -- xxx
#if 0
#include <iostream>
int main()
{
	using namespace std;

	return 0;
}
#endif
#pragma endregion

C++ Primer Plus 知识的讲解

第一章:预备知识

本章内容包括:
.C语言和C++的发展历史和基本原理
.过程性编程和面向对象编程
.c++是如何在C语言的基础上添加面向对象概念的
.c++是如何在C语言的基础上添加泛型编程概念的
.编程语言标准
.创建程序技巧

欢迎进入C++世界,这是一个令人兴奋的语言,他在C语言的基础上添加了面向对象编程和泛型编程的支持,在20时间90年代便是最重要的编程软件之一,并在21时间仍保持强劲势头。C++继承了C语言的高效,简洁,快速和可移植性的传统,C++面向对象的特性带来了全新的编程方法,这种方法是应付复杂程度不断提高的现代编程任务而设计的。C++的模板特性提供了另一种权限的编程方法----泛型编程,这三件发表即是福也是祸,一方面让C++语言功能强大,另一方面则意味着有更多的东西需要学习。
本章首先介绍C++的背景,然后介绍创建C++程序的一些基本原则,本书其他章节讲述如何使用C++ 语言,从最前线的基本知识开始,到面向对象编程(OOP)及其支持的新术语-----对象,类,封装,数据隐藏,多态和继承等,然后介绍他们对泛型编程的支持(当然,随着你对C++的学习,这些词汇将从花里胡哨的词语变为论述中必不可少的术语)

1.1 C++简介

C++融合了3种不同的编程方式:
1,C语言代表的过程性语言、
2,C++在C语言基础上添加的类代表的面向对象语言、
3,C++模板支持的泛型编程。
本章将简要介绍这些传统。不过首先,我们来看看这种传统对于学习 C++来说意味着什么。使用 C++的原因之一是为了利用其面向对象的特性。要利用这种特性,必须对标准 C语言知识有较深入的了解,因为它提供了基本类型、运算符、控制结构和语法规则。所以,如果已经对C有所了解,便可以学习C++了,但这并不仅仅是学习更多的关键字和结构,从C过渡到 C++的学习量就像从头学习C语言一样大。另外,如果先掌握了C语言,则在过渡到 C++时,必须摈弃一些编程习惯。如果不了解C语言,则学习 C++时需要掌握C语言的知识、OOP 知识以及泛型编程知识,但无需摈弃任何编程习惯。如果您认为学习C++可能需要扩展思维,这就对了。本书将以清晰的、帮助的方式,引导读者一步一个脚印地学习,因此扩展思维的过程是温和的,不至于让您的大脑接受不了。本书通过传授C语言基础知识和 C++新增的内容,带您步入C++的世界,因此不要求读者具备C语言知识。首先学习C++与C语言共有的一些特性。即使已经了解C语言,也会发现阅读本书的这一部分是一次很好的复习。另外,本章还介绍了一些对后面的学习十分重要的概念,指出了C++和C之间的区别。在牢固地掌握了C语言的基础知识后,就可以在此基础上学习C++方面的知识了。那时将学习对象和类以及C++是如何实现它们的,另外还将学习模板。
本书不是完整的 C++参考手册,不会探索该语言的每个细节,但将介绍所有的重要特性,包括模板异常和名称空间等。
下面简要地介绍一下C++的背景知识。

  1. 1.2 C++简史

在过去的几十年,计算机技术以令人惊讶的速度发展着,当前,笔记本电脑的计算速度和存储信息的能力超过了 20世纪60年代的大型机。很多程序员可能还记得,将数叠穿孔卡片提交给充斥整个房间的大型计算机系统的时代,而这种系统只有100KB的内存,比当今智能手机的内存都少得多。计算机语言也得到了发展,尽管变化可能不是天翻地覆的,但也是非常重要的。体积更大、功能更强的计算机引出了更大.
更复杂的程序,而这些程序在程序管理和维护方面带来了新的问题。在 20 世纪 70年代,C和 Pascal 这样的语言引领人们进入了结构化编程时代,这种机制把秩序和规程带进了迫切需要这种性质的领域中。除了提供结构化编程工具外,C还能生成简洁、快速运行的程序,并提供了处理硬件问题的能力,如管理通信端口和磁盘驱动器。这些因素使C语言成为 20世纪 80年代占统治地位的编程语言。同时,20世纪 80年代,人们也见证了一种新编程模式的成长:面向对象编程(OOP)。SmallTalk和C++语言具备这种功能。下面更深入地介绍C和OOP。

1.2.1 C语言

20世纪 70年代早期,贝尔实验室的 DennisRitchie致力于开发 UNIX操作系统(操作系统是能够管理计算机资源、处理计算机与用户之间交互的一组程序。例如,操作系统将系统提示符显示在屏幕上以提供终端式界面、提供管理窗口和鼠标的图形界面以及运行程序)。为完成这项工作,Ritchie 需要一种语言
它必须简洁,能够生成简洁、快速的程序,并能有效地控制硬件。传统上,程序员使用汇编语言来满足这些需求,汇编语言依赖于计算机的内部机器语言。然而,汇编语言是低级(low-level)语言,即直接操作硬件,如直接访问CPU寄存器和内存单元。因此汇编语言针对于特定的计算机处理器,要将汇编程序移植到另一种计算机上,必须使用不同的汇编语言重新编写程序。这有点像每次购买新车时,都发现设计人员改变了控制系统的位置和功能,客户不得不
重新学习驾驶。然而,UNIX是为在不同的计算机(或平台)上工作而设计的,这意味着它是一种高级语言。高级(high-level)语言致力于解决问题,而不针对特定的硬件。一种被称为编译器的特殊程序将高级语言翻译成特定计算机的内部语言。这样,就可以通过对每个平台使用不同的编译器来在不同的平台上使用同一个高级语言程序了。Ritchie希望有一种语言能将低级语言的效率、硬件访问能力和高级语言的通用性、可移植性融合在一起,于是他在旧语言的基础上开发了C语言。

  1. 1.2.2C语言编译原理

由于C++在℃语言的基础上移植了新的编程理念,因此我们首先来看一看C所遵循的旧的理念。一般来说,计算机语言要处理两个概念–数据和算法。数据是程序使用和处理的信息,而算法是程序使用的方法(参见图1.1)。C语言与当前最主流的语言一样,在最初面世时也是过程性(procedural)语言,这意味着它强调的是编程的算法方面。从概念上说,过程化编程首先要确定计算机应采取的操作,然后使用编程语言来实现这些操作。程序命令计算机按一系列流程生成特定的结果,就像菜谱指定了厨师做蛋糕时应遵循的一系列步骤一样。
随着程序规模的扩大,早期的程序语言(如FORTRAN和BASIC)都会遇到组织方面的问题。例如,程序经常使用分支语句,根据某种测试的结果,执行一组或另一组指令。很多旧式程序的执行路径很混乱(被称为“意大利面条式编程”),几乎不可能通过阅读程序来理解它,修改这种程序简直是一场灾难。为了解决这种问题,计算机科学家开发了一种更有序的编程方法–结构化编程(structuredprogramming)。C语言具有使用这种方法的特性。例如,结构化编程将分支(决定接下来应执行哪个指令)限制为一小组行为良好的结构。C语言的词汇表中就包含了这些结构(for循环、while循环、do while 循环和ifelse 语句)。另一个新原则是自顶向下(top-down)的设计。在C语言中,其理念是将大型程序分解成小型、便于管理的任务。如果其中的一项任务仍然过大,则将它分解为更小的任务。这一过程将一直持续下去,直到将程序划分为小型的、易于编写的模块(整理一下书房。先整理桌子、桌面、档案柜,然后整理书架。好,先从桌子开始,然后整理每个抽屉,从中间的那个抽屉开始整理也许我都可以管理这项任务)。C语言的设计有助于使用这种方法,它鼓励程序员开发程序单元(函数)来表示各个任务模块。如上所述,结构化编程技术反映了过程性编程的思想,根据执行的操作来构思一个程序。

  1. 1.2.3 面向对象编程

1.2.3 面向对象编程
虽然结构化编程的理念提高了程序的清晰度、可靠性,并使之便于维护,但它在编写大型程序时,仍面临着挑战。为应付这种挑战,OOP提供了一种新方法。与强调算法的过程性编程不同的是,OOP强调的是数据。OOP不像过程性编程那样,试图使问题满足语言的过程性方法,而是试图让语言来满足问题的要
求。其理念是设计与问题的本质特性相对应的数据格式。在 C++中,类是一种规范,它描述了这种新型数据格式,对象是根据这种规范构造的特定数据结构。例如,类可以描述公司管理人员的基本特征(姓名、头衔、工资、特长等),而对象则代表特定的管理人员(Guilford Sheepblat、副总裁、S925 000、知道如何恢复 Windows注册表)。通常,类规定了可使用哪些数据来表示对象以及可以对这些数据执行哪些操作。例如,假设正在开发一个能够绘制矩形的计算机绘图程序,则可以定义一个描述矩形的类。定义的数据部分应包括顶点的位置、长和宽、4条边的颜色和样式、矩形内部的填充颜色和图案等;定义的操作部分可以包括移动、改变大小、旋转、改变颜色和图案、将矩形复制到另一个位置上等操作。这样,当使用该程序来绘制矩形时,它将根据类定义创建一个对象。该对象保存了描述矩形的所有数据值,因此可以使用类方法来修改该矩形。如果绘制两个矩形,程序将创建两个对象,每个矩形对应一个。
OOP程序设计方法首先设计类,它们准确地表示了程序要处理的东西。例如,绘图程序可能定义表示矩形、直线、圆、画刷、画笔的类。类定义描述了对每个类可执行的操作,如移动圆或旋转直线。然后您便可以设计一个使用这些类的对象的程序。从低级组织(如类)到高级组织(如程序)的处理过程叫做自
下向上(bottom-up)的编程。OOP编程并不仅仅是将数据和方法合并为类定义。例如,OOP还有助于创建可重用的代码,这将减少大量的工作。信息隐藏可以保护数据,使其免遭不适当的访问。多态让您能够为运算符和函数创建多个定义,通过编程上下文来确定使用哪个定义。继承让您能够使用旧类派生出新类。正如接下来将看到的那样,OOP引入了很多新的理念,使用的编程方法不同于过程性编程。它不是将重点放在任务上,而是放在表示概念上。有时不一定使用自上向下的编程方法,而是使用自下向上的编程方法。本书将通过大量易于掌握的示例帮助读者理解这些要点。
设计有用、可靠的类是一项艰巨的任务,幸运的是,OOP语言使程序员在编程中能够轻松地使用已有的类。厂商提供了大量有用的类库,包括设计用于简化Windows或Macintosh 环境下编程的类库。C++真正的优点之一是:可以方便地重用和修改现有的、经过仔细测试的代码

  1. 1.2.4 C++和泛型编程

泛型编程(generic programming)是 C++支持的另一种编程模式。它与OOP的目标相同,即使重用代码和抽象通用概念的技术更简单。不过 OOP强调的是编程的数据方面,而泛型编程强调的是独立于特定数据类型。它们的侧重点不同。OOP是一个管理大型项目的工具,而泛型编程提供了执行常见任务(如对数据排序或合并链表)的工具。术语泛型(generic)指的是创建独立于类型的代码。C++的数据表示有多种类型–整数、小数、字符、字符串、用户定义的、由多种类型组成的复合结构。例如,要对不同类型的数据进行排序,通常必须为每种类型创建一个排序函数。泛型编程需要对语言进行扩展,以便可以只编写一个泛型(即不是特定类型的)函数,并将其用于各种实际类型。C++模板提供了完成这种任务的机制。

  1. 1.2.5 C++的起源

与C语言一样,C++也是在贝尔实验室诞生的,BjarneStroustrup于20世纪80年代在这里开发出了这种语言。用他自己的话来说,“C++主要是为了我的朋友和我不必再使用汇编语言、C语言或其他现代高级语言来编程而设计的。它的主要功能是可以更方便地编写出好程序,让每个程序员更加快乐”。
Biarne Stroustrup 的主页
Bjarme Stroustrup 设计并实现了C++编程语言,他是权威参考手册《The C++ Programming Language》和《The design and Evolution ofC++》的作者。读者应将他位于 AT&TLabs Research 上的个人网站作为首选的 C++书签:
http://www.research.att.com/-bs/该网站包括了 C++语言有趣的发展历史、Bjarne的传记材料和 C++FAQ。Bjarne 被问得最多的问题是:Bjarne Stroustrup应该如何读。您可以访问 Stroustrup的网站,阅读FAQ部分并下载.WAV 文件,亲自听一听。

Stroustrup 比较关心的是让 C++更有用,而不是实施特定的编程原理或风格。在确定 C++语言特性方面真正的编程需要比纯粹的原理更重要。Stroupstrup之所以在C的基础上创建C++,是因为C语言简洁、适合系统编程、使用广泛且与 UNIX 操作系统联系紧密。C++的 OOP方面是受到了计算机模拟语言 Simula67 的启发。Stroustrup加入了OOP特性和对C的泛型编程支持,但并没有对C的组件作很大的改动。因此,C+是C语言的超集,这意味着任何有效的C程序都是有效的 C++程序。它们之间有些细微的差异,但无足轻重。C++程序可以使用已有的C软件库。库是编程模块的集合,可以从程序中调用它们。库对很多常见的编程问题提供了可靠的解决方法,因此能节省程序员大量的时间和工作量。这也有助于C++的广泛传播。名称C++来自C语言中的递增运算符++,该运算符将变量加1。名称C++表明,它是C的扩充版本。
计算机程序将实际问题转换为计算机能够执行的一系列操作。OOP部分赋予了C++语言将问题所涉及的概念联系起来的能力,C部分则赋予了C++语言紧密联系硬件的能力(参见图1.2),这种能力上的结合成就了C++的广泛传播。从程序的一个方面转到另一个方面时,思维方式也要跟着转换(确实,有些OOP正统派把为C添加OOP特性看作是为猪插上翅膀,虽然这是头瘦骨嶙峋、非常能干的猪)。另外,C++是在C语言的基础上添加OOP特性,您可以忽略C++的面向对象特性,但将错过很
多有用的东西。在 C++获得一定程度的成功后,Stroustrup才添加了模板,这使得进行泛型编程成为可能。在模板特性被使用和改进后,人们才逐渐认识到,它们和 OOP同样重要–甚至比 OOP还重要,但有些人不这么认为。C+融合了OOP、泛型编程和传统的过程性方法,这表明C++强调的是实用价值,而不是意识形态方法,这也是该语言获得成功的原因之一。

C++的二重性
1,OOP提供了高级抽象。
2,C提供了低级硬件访问。

  1. 1.3 C++可移植性和标准

假设您为运行 Windows 2000 的老式奔腾 PC编写了一个很好用的 C++程序,而管理人员决定用使用不同操作系统(如MacOSX或Linux)和处理器(如SPARC处理器)的计算机替换它。该程序是否可以在新平台上运行呢?当然,必须使用为新平台设计的C++编译器对程序重新编译。但是否需要修改编写好的代码呢?如果在不修改代码的情况下,重新编译程序后,程序将运行良好,则该程序是可移植的。在可移植性方面存在两个障碍,其中的一个是硬件。硬件特定的程序是不可移植的。例如,直接控制IBMPC 视频卡的程序在涉及Sun 时将“胡言乱语”(将依赖于硬件的部分放在函数模块中可以最大限度地降低可移植性问题;这样只需重新编写这些模块即可)。本书将避免这种编程。可移植性的第二个障碍是语言上的差异。口语确实可能产生问题。约克郡的人对某个事件的描述,布鲁克林人可能就听不明白,虽然这两个地方的人都说英语。计算机语言也可能出现方言。WindowsXPC++的实现与 Red Hat Linux或 Macintosh OSX实现相同吗?虽然多数实现都希望其 C++版本与其他版本兼容但如果没有准确描述语言工作方式的公开标准,这将很难做到。因此,美国国家标准局(American NationalStandards Instiute,ANSI)在1990年设立了一个委员会(ANSI X3J16),专门负责制定 C++标准(ANSI制定了C语言标准)。国际标准化组织(ISO)很快通过自己的委员会(ISO-WG-21)加入了这个行列,创建了联合组织 ANSIISO,致力于制定 C++标准。
经过多年的努力,制定出了一个国际标准ISO/EC14882:1998,并于1998年获得了ISO、IEC(Inteational ElectrotechnicalCommitee,国际电工技术委员会)和 ANS】的批准。该标准常被称为 C++98它不仅描述了已有的 C++特性,还对该语言进行了扩展,添加了异常、运行阶段类型识别(RTTI)、模板和标准模板库(STL)。2003年,发布了C++标准第二版(IOSEC14882:2003);这个新版本是一次技术性修订,这意味着它对第一版进行了整理–修订错误、减少多义性等,但没有改变语言特性。这个版本常被称为 C++03。由于C++03没有改变语言特性,因此我们使用C++98 表示 C++98/C++2003。C++在不断发展。ISO标准委员会于2001年8月批准了新标准ISO/EC14882:2011,该标准以前称为C++11。与 C++98一样,C++11也新增了众多特性。另外,其目标是消除不一致性,让 C++学习和使用起来更容易。该标准还曾被称为C++0x,最初预期x为7或8,但标准制定工作是一个令人疲惫的缓慢过程。所幸的是,可将 0x视为十六进制数,这意味着委员会只需在 2015年前完成这项任务即可。根据这个度量标准,委员会还是提前完成了任务。
ISOC++标准还吸收了 ANSIC语言标准,因为C++应尽量是C语言的超集。这意味着在理想情况下,任何有效的C程序都应是有效的C++程序。ANSIC与对应的C++规则之间存在一些差别,但这种差别很小。实际上,ANSIC加入了C++首次引入的一些特性,如函数原型和类型限定符const。在 ANSIC出现之前,C语言社区遵循一种事实标准,该标准基于Kerighan 和 Ritchie 编写的《The CProgrammingLanguage》一书,通常被称为K&RC;ANSIC出现后,更简单的K&RC有时被称为经典C
(Classic C)。ANSIC标准不仅定义了C语言,还定义了一个ANSIC实现必须支持的标准C库。C++也使用了这个库;本书将其称为标准C库或标准库。另外,ANSI/ISOC++标准还提供了一个C++标准类库。最新的C标准为C99,ISO和ANSI分别于1999年和2000年批准了该标准。该标准在C语言中添加一些C++编译器支持的特性,如新的整型。
####1.3.1 C++的发展
Stroustrup编写的《The ProgrammingLanguage》包含 65 页的参考手册,它成了最初的 C++事实标准。
下一个事实标准是 Ellis 和 Stroustrup编写的《The Annotated C++ Reference Manual》。
C++98 标准新增了大量特性,其篇幅将近800页,且包含的说明很少。
C++11标准的篇幅长达1350页,对旧标准做了大量的补充。

  1. 1.4 程序创建的技巧

假设您编写了一个C++程序。如何让它运行起来呢?具体的步骤取决于计算机环境和使用的 C++编译器,但大体如下(参见图1.3)。
1.使用文本编辑器编写程序,并将其保存到文件中,这个文件就是程序的源代码。
2.编译源代码。这意味着运行一个程序,将源代码翻译为主机使用的内部语言–机器语言。包含了
翻译后的程序的文件就是程序的目标代码(obiectcode)3.将目标代码与其他代码链接起来。例如,C++程序通常使用库。C++库包含一系列计算机例程(被称为函数)的目标代码,这些函数可以执行诸如在屏幕上显示信息或计算平方根等任务。链接指的是将目标代码同使用的函数的目标代码以及一些标准的启动代码(startupcode)组合起来,生成程序的运行阶段版本。包含该最终产品的文件被称为可执行代码。本书将不断使用术语源代码,请记住该术语。
本书的程序都是通用的,可在任何支持C++98的系统中运行:但第18章的程序要求系统支持C++11。编写本书期间,有些编译器要求您使用特定的标记,让其支持部分C++11特性。例如,从4.3版起,g+1要求您编译源代码文件时使用标记-std=c++0x:
g+±std=C++0x use auto.cpp
创建程序的步骤可能各不相同,下面深入介绍这些步骤。

  1. 1.5 总结

随着计算机的功能越来越强大,计算机程序越来越庞大而复杂。为应对这种挑战,计算机语言也得到
了改进,以便编程过程更为简单。C语言新增了诸如控制结构和函数等特性,以便更好地控制程序流程,支持结构化和模块化程度更高的方法;而C++增加了对面向对象编程和泛型编程的支持,这有助于提高模块化和创建可重用代码,从而节省编程时间并提高程序的可靠性。
C++的流行导致大量用于各种计算平台的C++实现得以面世:而ISOC++标准(C++98/03和C++11)为确保众多实现的相互兼容提供了基础。这些标准规定了语言必须具备的特性、语言呈现出的行为、标准库函数、类和模板,旨在实现该语言在不同计算平台和实现之间的可移植性。
要创建 C++程序,可创建一个或多个源代码文件,其中包含了以 C++语言表示的程序。这些文件是文本文件,它们经过编译和链接后将得到机器语言文件,后者构成了可执行的程序。上述任务通常是在IDE中完成的,IDE 提供了用于创建源代码文件的文本编辑器、用于生成可执行文件的编译器和链接器以及其他资源,如项目管理和调试功能。然而,这些任务也可以在命令行环境中通过调用合适的工具来完成。

第二章 开始学习C++

本章内容包括
1,创建 C++程序。
2,C++程序的一般格式。
3,#include 编译指令。
4,main()函数。
5,使用 cout 对象进行输出。
6,在 C++程序中加入注释。
7,何时以及如何使用 endl。
8,声明和使用变量。
9,使用 cin 对象进行输入。
10,定义和使用简单函数。

要建造简单的房屋,首先要打地基、搭框架。如果一开始没有牢固的结构,后面就很难建造窗子、门框、圆屋顶和镶木地板的舞厅等。同样,学习计算机语言时,应从程序的基本结构开始学起。只有这样,才能一步一步了解其具体细节,如循环和对象等。本章对 C++程序的基本结构做一概述,并预览后面将介绍的主题,如函数和类。(这里的理念是,先介绍一些基本概念,这样可以激发读者接下去学习的兴趣。)

2.1进入C++

首先介绍一个显示消息的简单 C++程序。程序清单 2.1使用C++工具cout 生成字符输出。源代码中包含一些供读者阅读的注释,这些注释都以//打头,编译器将忽略它们。C++对大小写敏感,也就是说区分大写字符和小写字符。这意味着大小写必须与示例中相同。例如,该程序使用的是cout,如果将其替换为 Cout或COUT,程序将无法通过编译,并且编译器将指出使用了未知的标识符(编译器也是对拼写敏感的,因此请不要使用kout或 coot)。文件扩展名 cPp是一种表示 C++程序的常用方式,您可能需要使用第1章介绍的其他扩展名。
程序清单2.1myfirst.cpp

#include <iostream>

int main(void)
{
	using namespace std;

	int carrots;			//declare an integer variable

	carrots = 25;			//assign a value to the variable

	cout << "I have ";
	cout << carrots;		//display the value of the variable 
	cout << " carrots.";
	cout << endl;

	carrots = carrots - 1; //modify the variable 
	cout << "Crunch ,crunch . Now I have  " << carrots << " carrots." << endl;
	return 0;
}
																								**程序调整**

要在自己的系统上运行本书的示例,可能需要对其进行修改。有些窗口环境在独立的窗口中运行程序并在程序运行完毕后自动关闭该窗口。正如第1章讨论的,要让窗口一直打开,直到您按任何键,可在 retum语句前添加如下语句:
cin.get();
对于有些程序,要让窗口一直打开,直到您按任何键,必须添加两条这样的语句。第4章将更详细地介绍 cin.get( )。
如果您使用的系统很旧,它可能不支持C++98新增的特性。
有些程序要求编译器对 C++11 标准提供一定的支持。对于这样的程序,将明确的指出这一点,并在可能的情况下提供非 C++11 代码。

将该程序复制到您选择的编辑器中(或使用本书配套网站的源代码,详情请参阅封底)后,便可以 C++编译器创建可执行代码了(参见第1章的介绍)。下面是运行编译后的程序时得到的输出:

Come up and C++ me some time.
You won’t regret it!

C 语言输入和输出
如果已经使用过 C语言进行编程,则看到cout 函数(而不是 printf()函数)时可能会小吃一惊。事实上,C++能够使用 printf()、scanf()和其他所有标准C输入和输出函数,只需要包含常规 C语言的 stdio.h文件。不过本书介绍的是C++,所以将使用 C++的输入工具,它们在C版本的基础上作了很多改进。
您使用函数来创建 C++程序。通常,先将程序组织为主要任务,然后设计独立的函数来处理这些任务。
程序清单 2.1中的示例非常简单,只包含一个名为 main()的函数。myfirst.cpp示例包含下述元素。
注释,由前缀//标识。
预处理器编译指令**#include**。
函数头:int main()
编译指令 using namespace.
函数体,用{和}括起。
使用 C++的 cout 工具显示消息的语句。
结束 main()函数的 return 语句。
下面详细介绍这些元素。先来看看 **main()**函数,因为了解了 main()的作用后,main()前面的一些特性(如预处理器编译指令)将更易于理解。

2.1.1 main( )函数

去掉修饰后,程序清单2.1中的示例程序的基本结构如下:

int main()
	statements
return 0;

这几行表明有一个名为 main()的函数,并描述了该函数的行为。这几行代码构成了函数定义(functiondefinition)。该定义由两部分组成:第一行 int main()叫函数头(function heading),花括号({和})中包括的部分叫函数体。图 2.1对 main()函数做了说明。函数头对函数与程序其他部分之间的接口进行了总结;函
数体是指出函数应做什么的计算机指令。在C++中,每条完整的指令都称为语句。所有的语句都以分号结束,因此在输入示例代码时,请不要省略分号。
main()中最后一条语句叫做返回语句(retum statement),它结束该函数。本章将讲述有关返回语句的更多知识。
语句和分号
语句是要执行的操作。为理解源代码,编译器需要知道一条语句何时结束,另一条语句何时开始。有些语言使用语句分隔符。例如,FORTRAN通过行尾将语句分隔开来,Pascal使用分号分隔语句。在Pascal中,有些情况下可以省略分号,例如END前的语句后面,这种情况下,实际上并没有将两条语句分开。不过 C++与℃一样,也使用终止符(terminator),而不是分隔符。终止符是一个分号,它是语句的结束标记,是语句的组成部分,而不是语句之间的标记。结论是:在C+中,不能省略分号。
1.作为接口的函数头
就目前而言,需要记住的主要一点是,C++句法要求 main()函数的定义以函数头 int main()开始。本章后面的“函数”一节将详细讨论函数头句法,然而,为满足读者的好奇心,下面先预览一下。通常,C++函数可被其他函数激活或调用,函数头描述了函数与调用它的函数之间的接口。位于函数名前面的部分叫做函数返回类型,它描述的是从函数返回给调用它的函数的信息。函数名后括号中的部分叫做形参列表(argument list)或参数列表(parameter list);它描述的是从调用函数传递给被调用的函数的信息。这种通用格式用于main()时让人感到有些迷惑,因为通常并不从程序的其他部分调用 main()。然而,通常,main()被启动代码调用,而启动代码是由编译器添加到程序中的,是程序和操作系统(UNIX、Windows7或其他操作系统)之间的桥梁。事实上,该函数头描述的是 main()和操作系统之间的接口。来看一下 main()的接口描述,该接口从int 开始。C++函数可以给调用函数返回一个值,这个值叫做返回值(retum value)。在这里,从关键字 int 可知,main()返回一个整数值。接下来,是空括号。通常,C++函数在调用另一个函数时,可以将信息传递给该函数。括号中的函数头部分描述的就是这种信息。在这里,空括号意味着 main()函数不接受任何信息,或者 main()不接受任何参数。(main()不接受任何参数并不意味着 main()是不讲道理的、发号施令的函数。相反,术语参数(argument)只是计算机人员用来表示从一个函数传递给另一个函数的信息)。
简而言之,下面的函数头表明 main()函数可以给调用它的函数返回一个整数值,且不从调用它的函数那里获得任何信息:
int main()
很多现有的程序都使用经典C函数头:
main() //original c style

在C语言中,省略返回类型相当于说函数的类型为int。然而,C++逐步淘汰了这种用法。也可以使用下面的变体:

int main(void)//very explicit style
在括号中使用关键字 void 明确地指出,函数不接受任何参数。在C++(不是C)中,让括号空着与在括号中使用void等效(在C中,让括号空着意味着对是否接受参数保持沉默)。有些程序员使用下面的函数头,并省略返回语句:
void main()这在逻辑上是一致的,因为 void 返回类型意味着函数不返回任何值。该变体适用于很多系统,但由于它不是当前标准强制的一个选项,因此在有些系统上不能工作。因此,读者应避免使用这种格式,而应使用C++标准格式,这不需要做太多的工作就能完成。
最后,ANSIISO C++标准对那些抱怨必须在 main()函数最后包含一条返回语句过于繁琐的人做出了让步。如果编译器到达 main()函数末尾时没有遇到返回语句,则认为 main()函数以如下语句结尾:return 0;
这条隐含的返回语句只适用于 main()函数,而不适用于其他函数。
2.为什么 main()不能使用其他名称
之所以将 myfirst.cpp 程序中的函数命名为main(),原因是必须这样做。通常,C++程序必须包含一个名为 main()的函数(不是 Main()、MAIN()或 mane()。记住,大小写和拼写都要正确)。由于 myfirst.cpp程序只有一个函数,因此该函数必须担负起 main()的责任。在运行C++程序时,通常从main()函数开始执行。因此,如果没有main(),程序将不完整,编译器将指出未定义main()函数。
存在一些例外情况。例如,在 Windows 编程中,可以编写一个动态链接库(DLL)模块,这是其他 Windows程序可以使用的代码。由于 DLL 模块不是独立的程序,因此不需要 main()。用于专用环境的程序–如机器人中的控制器芯片–可能不需要 main()。有些编程环境提供一个框架程序,该程序调用一些非标准函数,如 tmain()。在这种情况下,有一个隐藏的 main(),它调用_tmain()。但常规的独立程序都需要 main(),本书讨论的都是这种程序。

2.1.2 C++注释

C++注释以双斜杠(//)打头。注释是程序员为读者提供的说明,通常标识程序的一部分或解释代码的某个方面。编译器忽略注释,毕竟,它对C++的了解至少和程序员一样,在任何情况下,它都不能理解注释。对编译器而言,程序清单 2.1就像没有注释一样:

#include <iostream>
int main()
using namespace std;
cout <"Come up and C++ me some time.";
cout << endl;
cout <s"You won't regret it!" << endl;
return 0;

C++注释以//打头,到行尾结束。注释可以位于单独的一行上,也可以和代码位于同一行。请注意程序清单 2.1的第一行:
//myfirst.cppdisplays a message
本书所有的程序都以注释开始,这些注释指出了源代码的文件名并简要地总结了该程序。在第1章中介绍过,源代码的文件扩展名取决于所用的C++系统。在其他系统中,文件名可能为myfirst.C或myfirst.cxx。
提示:应使用注释来说明程序。程序越复杂,注释的价值越大。注释不仅有助于他人理解这些代码也有助于程序员自己理解代码,特别是隔了一段时间没有接触该程序的情况下。
C-风格注释
C++也能够识别C注释,C注释包括在符号//之间
:#include /aC-style comment/
由于C-风格注释以*/结束,而不是到行尾结束,因此可以跨越多行。可以在程序中使用 C或 C++风格的注释,也可以同时使用这两种注释。但应尽量使用C++注释,因为这不涉及到结尾符号与起始符号的正确配对,所以它产生问题的可能性很小。事实上,C99标准也在C语言中添加了//注释。

2.1.3 C++预处理器和iostream 文件

下面简要介绍一下需要知道的一些知识。如果程序要使用C++输入或输出工具,请提供这样两行代码:#include siostream>
using namespace std可使用其他代码替换第2行,这里使用这行代码旨在简化该程序(如果编译器不接受这几行代码,则说明它没有遵守标准 C++98,使用它来编译本书的示例时,将出现众多其他的问题)。为使程序正常工作,
只需要知道这些。下面更深入地介绍一下这些内容。C++和C一样,也使用一个预处理器,该程序在进行主编译之前对源文件进行处理(第1章介绍过,有些C++实现使用翻译器程序将C++程序转换为C程序。虽然翻译器也是一种预处理器,但这里不讨论这种预处理器,而只讨论这样的预处理器,即它处理名称以#开头的编译指令)。不必执行任何特殊的操作来调用该预处理器,它会在编译程序时自动运行。
程序清单 2.1使用了#include 编译指令:

#include //a PREPROCESSOR directive
该编译指令导致预处理器将iostrcam 文件的内容添加到程序中。这是一种典型的预处理器操作:在源
代码被编译之前,替换或添加文本。这提出了一个问题:为什么要将iostream 文件的内容添加到程序中呢?答案涉及程序与外部世界之间的通信。iostream 中的io指的是输入(进入程序的信息)和输出(从程序中发送出去的信息)。C++的输入1输出方案涉及 iostream 文件中的多个定义。为了使用 cout来显示消息,第一个程序需要这些定义。#include编译指令导致 iostream 文件的内容随源代码文件的内容一起被发送给编译器。实际上,iostream 文件的内容将取代程序中的代码行#include。原始文件没有被修改,而是将源代码文件和iostream 组合成一个复合文件,编译的下一阶段将使用该文件。
注意:使用 cin和cout进行输入和输出的程序必须包含文件iostream。

2.1.4 头文件名

像 iostream 这样的文件叫做包含文件(include file)–由于它们被包含在其他文件中;也叫头文件(header fle)–由于它们被包含在文件起始处。C++编译器自带了很多头文件,每个头文件都支持一组特定的工具。C语言的传统是,头文件使用扩展名h,将其作为一种通过名称标识文件类型的简单方式。例如,头文件 math.h支持各种C语言数学函数,但C++的用法变了。现在,对老式C的头文件保留了扩展名h(C++程序仍可以使用这种文件),而C++头文件则没有扩展名。有些C头文件被转换为 C++头文件,这些文件被重新命名,去掉了扩展名h(使之成为C++风格的名称),并在文件名称前面加上前缀c(表明来自C语言)。例如,C++版本的math.h为cmath。有时C头文件的C版本和 C++版本相同,而有时候新版本做了一些修改。对于纯粹的C++头文件(如iostream)来说,去掉h不只是形式上的变化,没有h的头文件也可以包含名称空间–本章的下一个主题。表 2.1对头文件的命名约定进行了总结。

2.1.5 名称空间

如果使用 iostream,而不是iostream.h,则应使用下面的名称空间编译指令来使iostream 中的定义对程序可用:
using namespace std;
这叫做 using 编译指令。最简单的办法是,现在接受这个编译指令,以后再考虑它(例如,到第9章
再考虑它)。但这里还是简要地介绍它,以免您一头雾水。名称空间支持是一项C++特性,旨在让您编写大型程序以及将多个厂商现有的代码组合起来的程序时更容易,它还有助于组织程序。一个潜在的问题是,可能使用两个已封装好的产品,而它们都包含一个名为wanda()的函数。这样,使用wanda()函数时,编译器将不知道指的是哪个版本。名称空间让厂商能够将其产品封装在一个叫做名称空间的单元中,这样就可以用名称空间的名称来指出想使用哪个厂商的产品。因此,Microfop Industries可以将其定义放到一个名为Microfop的名称空间中。这样,其 wanda()函数的全称为 Microfop::wanda():同样,Piscine 公司的 wanda()版本可以表示为Piscine::wanda()。这样,程序就可以使用名称空间来区分不同的版本了:
//use Microflop namespace versionMicroflop::wanda(“go dancing?”);Piscine::wanda(“a fish named Desire”);// use piscine namespace version
按照这种方式,类、函数和变量便是C++编译器的标准组件,它们现在都被放置在名称空间std中。仅当头文件没有扩展名h时,情况才是如此。这意味着在iostream 中定义的用于输出的 cout 变量实际上是std::cout,而 endl 实际上是 std::endl。因此,可以省略编译指令using,以下述方式进行编码:
std::cout <e"Come up and C++me some time.";std::cout << std::endl;
然而,多数用户并不喜欢将引入名称空间之前的代码(使用iostream.h和cout)转换为名称空间代码(使用 iostreamstd:cout),除非他们可以不费力地完成这种转换。于是,using编译指令应运而生。下面的一行代码表明,可以使用 std 名称空间中定义的名称,而不必使用 std::前缀:using nawespace std:
这个 using 编译指令使得 std 名称空间中的所有名称都可用。这是一种偷懒的做法,在大型项目中一个潜在的问题。更好的方法是,只使所需的名称可用,这可以通过使用using声明来实现:
/make cout availableusing std::cout;
make endl availableusing std::endl:using std::cin;
/make cin available

用这些编译指令替换下述代码后,便可以使用cin和cout,而不必加上std::前缀:using namespace std;//lazy approach,all names available然而,要使用iostream中的其他名称,必须将它们分别加到using 列表中。本书首先采用这种偷懒的方法,其原因有两个。首先,对于简单程序而言,采用何种名称空间管理方法无关紧要;其次,本书的重点是介绍C++的基本方面。本书后面将采用其他名称空间管理技术。

2.1.6 使用 cout 进行 C++输出

现在来看一看如何显示消息。myfrst.cpp程序使用下面的C++语句:
cout <<“Come up and e++ me some time.”;
双引号括起的部分是要打印的消息。在C++中,用双引号括起的一系列字符叫做字符串,因为它是由若干字符组合而成的。<<符号表示该语句将把这个字符串发送给cout;该符号指出了信息流动的路径。cout是什么呢?它是一个预定义的对象,知道如何显示字符串、数字和单个字符等(第1章介绍过,对象是类的特定实例,而类定义了数据的存储和使用方式)。
马上就使用对象可能有些困难,因为几章后才会介绍对象。实际上,这演示了对象的长处之—不用了解对象的内部情况,就可以使用它。只需要知道它的接口,即如何使用它。cout对象有一个简单的接口,如果 string是一个字符串,则下面的代码将显示该字符串:
cout << string;
对于显示字符串而言,只需知道这些即可。然而,现在来看看 C++从概念上如何解释这个过程。从概念上看,输出是一个流,即从程序流出的一系列字符。cout对象表示这种流,其属性是在iostream 文件中定义的。cout的对象属性包括一个插入运算符(<<),它可以将其右侧的信息插入到流中。请看下面的语句(注意结尾的分号):
cout “Come up and++me some time.”;
它将字符串“Come upand C++me some time.”插入到输出流中。因此,与其说程序显示了一条消息,不如说它将一个字符串插入到了输出流中。不知道为什么,后者听起来更好一点(参见图 2.2)。

初识迈算将重载
如果熟悉C后才开始学习 C++,则可能注意到了,插入运算符(<<)看上去就像按位左移运算符(<<),这是一个运算符重载的例子,通过重载,同一个运算符将有不同的含义。编译器通过上下文来确定运算符的含义。C本身也有一些运算符重载的情况。例如,&符号既表示地址运算符,又表示按位 AND运算符:
第2章开始学习C++
19
既表示乘法,又表示对指针解除引用。这里重要的不是这些运算符的具体功能,而是同一个符号可以有多种含义,而编译器可以根据上下文来确定其含义(这和确定“sound card”中的“sound”与“sound financialbasic”中的“sound”的含义是一样的)。C++扩展了运算符重载的概念,允许为用户定义的类型(类)重新定义运算符的含义。
1.控制符endl
现在来看看程序清单 2.1中第二个输出流中看起来有些古怪的符号:cout <e endl;
cndl是一个特殊的 C++符号,表示一个重要的概念:重起一行。在输出流中插入cndl将导致屏幕光标移到下一行开头。诸如 endl 等对于 cout来说有特殊含义的特殊符号被称为控制符(manipulator)。和 cout一样,endl也是在头文件iostream中定义的,且位于名称空间std中。
打印字符串时,cout不会自动移到下一行,因此在程序清单2.1中,第一条cout 语句将光标留在输出字符串的后面。每条cout 语句的输出从前一个输出的末尾开始,因此如果省略程序清单2.1中的end,得到的输出将如下:
Come up and ++ me some time.You won’t regret it!
从上述输出可知,Y紧跟在句点后面。下面来看另一个例子,假设有如下代码:cout < “The Good,the”:
cout <<“Bad,”;
cout <s"and the Ukulele
;
cout << endl;

其输出将如下:
The Good,theBad,and the Ukulele
同样,每个字符串紧接在前一个字符串的后面。如果要在两个字符串之间留一个空格,必须将空格包含在字符串中。注意,要尝试上述输出示例,必须将代码放到完整的程序中,该程序包含一个main()函数头以及起始和结束花括号。
2.换行符
C++还提供了另一种在输出中指示换行的旧式方法:C语言符号n
:cout se “What’s next?n”;n means start a new line
\n被视为一个字符,名为换行符。显示字符串时,在字符串中包含换行符,而不是在末尾加上endl,可减少输入量:
cout << “Pluto is a dwarf planet.\n”;//show text,go to next line
cout << “Pluto is a dwarf planet.”<< endl;//show text,go to next line

另一方面,如果要生成一个空行,则两种方法的输入量相同,但对大多数人而言,输入 endl 更为方便:
cout << “\n”;/start a new line
cout < endl;/start a new line
本书中显示用引号括起的字符串时,通常使用换行符,在其他情况下则使用控制符endl。一个差别是,cndl确保程序继续运行前刷新输出(将其立即显示在屏幕上):而使用“"”不能提供这样的保证,这意味着在有些系统中,有时可能在您输入信息后才会出现提示。
换行符是一种被称为“转义序列”的按键组合,转义序列将在第3章做更详细的讨论。

2.1.7 C++源代码的格式化

有些语言(如FORTRAN)是面向行的,即每条语句占一行。对于这些语言来说,回车的作用是将语句分开。然而,在 C++中,分号标示了语句的结尾。因此,在C++中,回车的作用就和空格或制表符相同。也就是说,在C++中,通常可以在能够使用回车的地方使用空格,反之亦然。这说明既可以把一条语句放

在几行上,也可以把几条语句放在同一行上。例如,可以将myfrst.cpp重新格式化为如下所示:

#include ciostream>
int
main
()using
nаmesрace
std; cout
CC
"Come up and C++ me some time.
Cout <
endl;cout <<
"You won't regret it!" <<
endl;return 0

这样虽然不太好看,但仍然是合法的代码。必须遵守一些规则,具体地说,在C和C+中,不能把空格制表符或回车放在元素(比如名称)中间,也不能把回车放在字符串中间。下面是一个不能这样做的例子:

int ma in)
//INVALIDspace in name
¥e
turn 0://INVALID-carriage return in word
cout <<"Behold the Beans
of Beauty!";//INVALID carriage return in string

然而,C++11新增的原始(raw)字符串可包含回车,这将在第4章简要地讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值