2. #include指令—— 头文件
在注释之后有一个#include指令:
#include
之所以称其为指令,是因为它命令编译器完成某项任务—— 此处是在编译之前,在此程序的源文件中插入文件iostream的内容,该文件名位于尖括号之间。iostream文件称为头文件,因为它总是插入到另一个源文件中。iostream头文件是标准C++库的一部分,它包含一些使用输入和输出语句所需的定义。如果没有在此程序中包括iostream的内容,那么不能编译这个程序,因为在这个程序中使用的输出语句依赖该文件中的一些定义。Visual C++提供了许多不同的标准头文件,它们具有各种各样的功能。在进一步学习语言工具时,将看到更多的头文件。
由#include指令插入的文件的名称不一定写在尖括号之间。头文件名也可以写在双引号中。因此上面的代码也可以写成:
#include "iostream"
两者之间的唯一区别是编译器将在什么地方查找此文件。如果头文件名是用双引号引起来的,则编译器先在包含此指令的源文件所在的目录中搜索头文件。如果头文件未找到,编译器再搜索存储标准头文件的目录。
如果文件名是用尖括号括起来的,则编译器只搜索包含标准头文件的目录。因此,想在源文件中包含标准头文件时,应该将文件名用尖括号括起来,因为这样的搜索速度更快。而要包含其他头文件,一般是自己创建的头文件,则应该将文件名用双引号引起来;否则,根本找不到。
#include语句是几个预处理器指令中的一个,本书后面将介绍其他预处理指令。编辑器会在编辑窗口中用蓝色突出显示它们。预处理器指令是由编译的预处理阶段执行的命令,这个阶段在代码编译成目标代码之前执行,在编译源代码之前,预处理器指令通常以某种方式作用于它们。预处理器指令都以#字符开头。
3. 名称空间和using声明
如第1章所述,标准库是一个大型的例程集合,用于执行许多常见的任务,如处理输入和输出,以及执行基本的数学计算。由于标准库中的这些例程以及其他具有名称的事物数量巨大,因此用户使用的名称可能无意中与标准库中的名称雷同。名称空间是一种机制,它可以将无意中使用重名的风险降至最低,其方法是将一组给定的名称如标准库中的名称与一种姓family name关联起来,这种姓就是名称空间名称。
在名称空间的代码中定义的每个名称都有一个关联的名称空间名称。标准库工具定义在std名称空间内,所以标准库中的每一项都有自己的名称,以及作为限定符的名称空间名称std。标准库中cout和endl的全名是std::cout和std::endl,第1章介绍过这些名称。将名称空间名称和实体名分隔开的两个冒号构成了称为“作用域解析运算符”的运算符,本书后面将介绍这种运算符的其他用途。在程序中使用全名会使代码看起来有点混乱,所以最好使用不由名称空间名称std限定的简化名。在前面的程序中,iostream的#include指令后面的两行代码使之得以实现:
using std::cout;
using std::endl;
这些是using声明,它们告诉编译器,要在不指定名称空间名称的情况下使用名称空间std中的名称cout和endl。编译器假定,在第一个using声明之后,只要使用名称cout,就表示std::cout。名称cout表示对应于命令行的标准输出流,名称endl表示换行符,并刷新输出缓存。本章后面会详细介绍名称空间,包括如何自定义名称空间。
2.1.1 main函数
上述示例中的函数main包括将它定义为main的函数头,以及从第一个左大括号{到对应的右大括号}之间的所有语句。这对括号将这个函数中的可执行语句包围起来,它们总称为函数体。
所有函数都包括一个定义函数名称的头,然后是函数体,它由包括在大括号之间的一些程序语句组成。函数体也可以不包含任何语句,这时它不做任何事情。
不做任何事情的函数似乎有些多余,但是在编写大程序时,一开始可以先勾画出函数中的完整程序结构,而忽略许多函数的代码,使它们有一个空的或者最小的函数体。这意味着,可以随时编译和执行包含所有函数的整个程序,并逐步给函数添加详细的代码。
2.1.2 程序语句
main函数体的每个程序语句都以一个分号结束。分号表示语句的结束,而不是这一行的结束。因此,为了使代码更易于理解,可以把一个语句扩展成几行,也可以把几个语句放在同一行中。程序语句是定义程序功能的基本单元。这有点像文章中一个段落的句子,每个句子都独立地表达一个行为或想法,和这个段落中的其他句子联系和组合起来,就表达出比较全面的想法。一个语句就是计算机将要执行的一个行为的自包含定义,和其他语句组合起来, 就可以定义比较复杂的行为或计算。
函数的行为始终由一些语句来表达,每个语句都以分号结束。看看刚才编写的示例中的语句,大致了解它是如何运行的。本章后面将讨论每种类型的语句。
在main函数体中,第一个语句是:
int apples, oranges; Declare two integer variables
这个语句定义了两个变量apples和oranges。变量是一段已命名的计算机内存,用于存储数据,引入一个或多个变量名称的语句称为变量声明。关键字int表明apples和oranges变量将存储整数值。每当把一个变量的名称引入程序时,都要指定它将存储的数据类型,这称为变量的类型。
接下来的这个语句声明了另一个整型变量fruit:
int fruit; ...then another one
虽然可以在同一个语句中声明几个变量,如同前面的语句声明apples和oranges那样。但是,一般最好用一个语句声明一个变量,独占一行,这样就可以单独注释,以解释它们的用途。
示例中的下一行代码是:
apples = 5; oranges = 6; Set initial values
这行代码包含两个语句,每个语句都以一个分号结束。这样做的目的是说明可以把多个语句放在一行中。这不是强制的,但良好的编程习惯一般是一行只编写一个语句,使代码较容易理解。良好的编程习惯是采用使代码易于理解、且使出错的可能性降至最低的编码方法。
这两个语句分别将数值5和6存储到变量apples和oranges中。这些语句称为赋值语句,因为它们把新值赋给变量,=是赋值运算符。
下一个语句是:
fruit = apples + oranges; Get the total fruit
这也是一个赋值语句,但稍有不同,因为在赋值运算符的右边是一个算术表达式。这个语句把存储在变量apples和oranges中的数值相加,然后在变量fruit中存储结果。
下面的3个语句是:
cout endl; Start output on a new line
cout "Oranges are not the only fruit... " endl
"- and we have " fruit " fruits in all.";
cout endl; Output a new line character
它们都是输出语句。第一个语句把由endl表示的换行符发送到屏幕的命令行中。在C++中,输入的来源或输出的目的地称为流。名称cout指定“标准的”输出流,运算符表明,该运算符右边的内容将发送到输出流cout。运算符“指出”数据流动的方向,从这个运算符右边的变量、字符串或表达式到左边的输出目的地。因此,在第一个语句中,由名称endl表示的值即换行符将发送到由名称cout标识的流—— 传输到cout的数据会写入命令行。把endl发送到流,也会刷新流缓存,然后把所有输出发送到命令行。
名称cout和运算符的含义定义在头文件iostream中,该文件利用#include指令在程序代码中添加。cout是标准库中的名称,所以它在名称空间std内。如果不使用using指令,就不会识别cout,除非使用了其全限定名std::cout。cout定义为表示标准输出流,因此不应当把它用于其他目的,将相同的名称用于不同的事情很可能引起混淆。
第2个输出语句扩展成如下两行:
cout "Oranges are not the only fruit... " endl
"- and we have " fruit " fruits in all.";
如前所述,每个语句都可以扩展成许多行。语句的结束始终用分号表示,而不是一行的结束。编译器将读取连续的行,并把它们组合成一个语句,直至发现定义该语句结束的分号。当然,这也意味着,如果忘记在语句的结尾处放置分号,那么编译器将假定下一行是同一语句的一部分,并将它们连接到一起。这通常会产生编译器无法理解的东西,所以您将得到一个错误消息。