首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

下面介绍一个非常简单的C++程序,了解C++程序的组成。现在读者不需要输入代码,只是了解一下建立程序的过程。这里也不详细介绍所有的细节,因为这些内容将在后面的章节中探讨。如图1-2所示。

图1-2中所示的程序会显示如下消息:

The best place to start is at the beginning

这个程序不是很有用,但说明了几点。该程序由一个函数main()组成。函数是代码的一个自包含块,用一个名称表示,在本例中是main。程序中还可以有许多其他代码,但每个C++程序至少要包含函数main(),且只能有一个main()函数。C++程序的执行总是从main()中的第一条语句开始。

图1-2 一个简单的C++程序

该函数的第一行语句是:

int main()

这行语句指出,这是函数main的开始。开头的int表示这个函数在执行完后返回一个整数值。因为这是函数main(),所以最初调用它的操作系统会接收这个值。

函数main()包含两个可执行语句,每个语句放在一行上:

cout << "The best place to start is at the beginning";

return 0;

这两个语句会按顺序执行。通常情况下,函数中的语句总是按顺序执行,除非有一个语句改变了执行顺序。第4章将介绍什么类型的语句可以改变执行顺序。

在C++中,输入和输出是使用流来执行的。如果要从程序中输出消息,可以把该消息放在输出流中,如果要输入消息,则把它放在输入流中。因此,流是数据源或数据池的一种抽象表示。在程序执行时,每个流都关联着某个设备,关联着数据源的流就是输入流,关联着数据目的地的就是输出流。对数据源或数据池使用抽象表示的优点是,无论流代表什么,编程都是相同的。例如,从磁盘文件中读取数据的方式与从键盘上读取完全相同。在C++中,标准的输出流和输入流称为cout和cin,在默认情况下,它们分别对应计算机屏幕和键盘。

main()中的第一行代码利用插入运算符<<把字符串The best place to start is at the beginning放在输出流中,从而把它输出到屏幕上。在编写涉及到输入的程序时,应使用提取运算符>>。

头文件包含的代码定义了一组可以在需要时包含在程序源文件中的标准功能。C++标准库中提供的功能存储在头文件中,但头文件不仅仅用于这个目的。我们可以创建自己的头文件,包含自己的代码。在这个程序中,名称cout在头文件iostream中定义。这是一个标准的头文件,它提供了在C++中使用标准输入和输出功能所需要的定义。如果程序不包含下面的代码行:

#include <iostream>

就不会进行编译,因为<iostream>头文件包含了cout的定义,没有它,编译器就不知道cout是什么。这是一个预处理指令,详见本书后面的内容。#include的作用是把<iostream>头文件的内容插入程序源文件中该指令所在的位置。这是在程序编译之前完成的。

提示:

在尖括号和标准头文件名之间没有空格。在许多编译器中,两个尖括号<和>之间的空格是很重要的,如果在这里插入了空格,程序就可能不编译。

函数体中的第二个语句,也是最后一个语句:

return 0;

结束了该程序,把控制权返回给操作系统。它还把值0返回给操作系统。也可以返回其他值,来表示程序的不同结束条件,操作系统还可以利用该值来判断程序是否执行成功。一般情况下,0表示程序正常结束,非0值表示程序不正常结束。但是,非0返回值是否起作用取决于操作系统。

1.3.1 名称

C++程序中的许多元素都有用来表示它们的名称,也称为标识符。在C++程序中,可以命名的5种元素是:

(1) 函数。函数是自包含的、可执行代码的命名块。第8章将详细讨论如何定义函数。

(2) 变量。变量是内存中的指定区域,用于存储数据项。第2章将论述变量。

(3) 类型。类型是可以存储的数据种类。例如类型int用于存储整数。第2章和后续的章节将介绍类型,尤其是第11章。

(4) 标签。标签提供了表示特定语句的方式。它们很少使用,第4章将详细介绍。

(5) 命名空间。命名空间是用一个集合名称标识程序中一组命名项的方式。这听起来可能让人混淆,但不必担心,稍后就介绍命名空间,第10章将详细论述。

在C++中,名称可以包含大小写拉丁字母a~z和A~Z、下划线(_)和数字0~9。C++的ANSI标准还允许在名称中包含通用字符集(Universal Character Set)(稍后介绍)中的字符。

ANSI标准还允许名称有任意长度,但有的编译器对此有某种长度限制,这个限制常常比较宽(几千个字符),不是一个严格的限制。

空白在C++中用于表示空格、垂直或水平制表符、换行符和换页符。不能在名称的中间加上空白字符,否则,编译器就不会把该名称看作是一个名称,而是看作两个或多个名称,从而导致处理不正确。另一个限制是名称不能以数字开头。

下面是一些合法的名称例子:

value2 Mephistopheles BettyMay Earth_weight PI

下面这些名称就不合法:

8Ball Mary-Ann Betty+May Earth-weight 2PI

提示:

包含两个下划线的名称,或者以下划线开头,后跟一个大写字母的名称,是C++标准库的保留名称,在程序中不应使用这类名称。编译器不会检查这类名称,用户只能在程序出错时发现有一个冲突的名称。

使用扩展字符集的名称

如上一节所述,C++标准允许在名称中包含UCS字符。可以把这些字符写作\Udddddddd格式或\udddd格式,其中d是UCS码中某字符的的16进制数字。

但没有人希望在名称中包含这样的字符,在名称中嵌入\U后跟一组16进制数字不会提高代码的可读性。允许在名称中使用UCS字符的目的是为了让编译器编写人员可以包容用非英语的其他语言编写的字符,例如希腊语、韩语或俄语。

C++标准允许实现编译器,以使用任何字符来指定名称。利用这一点的所有编译器在开始编译代码之前,都必须把非基本集合的字符转换为如前面所示的UCS字符的标准表示。例如,在源代码中,有人编写了名称KHHRa,它对俄国程序员是有意义的。编译器在编译代码之前,先在内部把这个名称转换为UCS字符的一个标准化表示,例如/u041A/u043D/u0438/u0433 /u0430。实际上,无论在源代码中使用什么字符集指定名称,最终都会得到基本集合中的字符,再加上UCS字符\Udddddddd或\udddd。

在名称中,必须总是显式使用基本字符集中的字符a~z、A~Z、0~9和下划线。在名称中为这些字符使用UCS码是非法的。其原因是标准没有指定用于基本字符集的编码,所以这个任务就留给了编译器。因此,如果要根据UCS码指定基本字符,该字符可能不同于显式指定字符时编译器为该字符使用的编码,从而产生混乱的结果。

注意,并没有要求编译器支持在指定名称时显式使用字符,如果编译器不支持这些字符,在处理之前,这些字符就必须映射为UCS格式。遵循该标准的编译器必须在任何情况下都支持名称使用基本字符集中的字符,并允许以本节开头介绍的不太友好的方式使用UCS字符。

1.3.2 命名空间

在上面的简单C++程序中,有一行代码没有解释。为了理解这行代码,需要知道什么是命名空间。为了说明命名空间的含义,下面先讨论名称。上面C++程序中还没有解释的代码行如下:

using namespace std;

在前一节讨论的标识符规则中,可以为程序中的元素选择使用任何名称。显然,可以为标准库中已经用于其他目的的元素选择一个名称。同样,如果两个或多个程序员为同一个大型工程的不同部分工作,就会有潜在的名称冲突。显然,为两个或多个不同的元素使用相同的名称会导致冲突,命名空间就解决了这个问题。

命名空间的名称有点像姓氏。家庭中的每个成员都有自己的姓名,在大多数家庭中,每个家庭成员都有一个惟一的名字。在Smith家中,有Jack、Jill、Jean和Jonah。在家庭成员之间,用名字来指代每个人。但是,其他家庭的成员可能与Smith家的成员有相同的名字。例如,在Jones家中,其成员的名字是John、Jean、Jeremiah和Jonah。Jeremiah Jones在称呼Jean时,显然是指Jean Jones。如果他想指代Smith家中的Jean,就要使用全名Jean Smith。如果不是这两个家庭的成员,就只能使用每个人的全名来指代他本人,例如Jack Smith或Jonah Jones。

这就是命名空间的作用。命名空间的名称类似于姓氏。在命名空间内部,可以使用其成员的名字。在命名空间的外部,就只能把某个实体的名字和命名空间的名称组合起来,表示该命名空间中的实体。命名空间的目的是提供一种机制,使大程序的各个部分中因出现重名而导致冲突的可能性降到最低。一般情况下,一个程序中包含几个不同的命名空间。

C++标准库中的实体都是在命名空间std中定义的,所以标准库中的所有实体名都用std来限定。cout的全名就是std::cout,其中的两个冒号有一个非常好听的名称:范围解析运算符,稍后详述。在这个例子中,该运算符把命名空间的名称std和流的名称cout分隔开来。

在这个简单的C++程序中,开头的using指令表示我们希望在每次引用命名空间std中的元素时,不指定命名空间的名称。继续前面的类推,使程序文件成为std家族的一组荣誉成员,就可以只用名字来引用每个成员了。其优点之一是不需要把cout表示为std::cout,这样程序代码就更简单。如果省略using指令,就必须把输出语句写为:

std::cout <<"The best place to start is at the beginning";

当然,尽管这使代码略为复杂一些,但这样编写出的代码比较安全,也比较好。Using指令的作用是允许使用命名空间中的某个名称,而不必用命名空间的名称来限定它。有时也可以这么做:用命名空间的名称明确限定cout,就不必在程序中使命名空间中的所有名称都可用了。这样,在程序中定义的任何名称和在命名空间中定义的名称就不可能出现冲突了。

如果把这个例子的程序代码改成下面的形式,就比较好:

// Program 1.1 A simple C++ program

#include <iostream>

int main() {

std::cout <<"The best place to start is at the beginning";

return 0;

}

但是,这些代码虽然比较安全,如果代码中有许多std::cout,代码看起来就很混乱了。我们还必须在程序的许多地方重复输入std::,在这种情况下,可以使用using指令在程序源文件中引入命名空间中的一个名称。例如,使用下面的指令可以在程序文件中引入std命名空间中的名称cout:

using std::cout;

使用这个指令,可以两全其美:以未限定的方式使用std命名空间中的名称cout,代码中的名称也不会与std命名空间中的其他名称冲突,因为它们不使用std限定符是不能使用的。程序现在变成:

// Program 1.1A A simple C++ program

#include <iostream>

using std::cout;

int main() {

cout <<"The best place to start is at the beginning";

return 0;

}

当然,也可以为每个名称使用using指令,把std命名空间中的一些名称引入程序文件。应为代码中常用的名称使用using指令,通过完全限定的名称来访问std命名空间中不太常用的其他名称。

命名空间和using指令的内容远比这里介绍的多,详见第10章。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论