程序结构

学习一门编程语言最好的方法就是编写程序。通常,初学者编写的第一个程序叫作“Hello World”,它只会在你的电脑屏幕上打印出“Hello World”。虽然这个程序非常简单,但它包含了 C++ 程序所拥有的所有基本组件。

// my first program in C++
#include <iostream>

int main()
{
  std::cout << "Hello World!";
}
Hello World!

上方左侧面板显示了该程序的 C++ 代码。右侧面板显示了程序由计算机执行后的结果。面板左侧的灰色数字是行号,方便讨论程序和研究错误。它们不是程序的一部分。

让我们逐行研究这个程序:

第 1 行:// my first program in C++
两个斜杠符号表示该行余下的部分是程序员插入的注释,它对程序的行为没有影响。程序员使用注释来对代码或程序进行简短的解释或说明。在这里,它是一个对程序的简要介绍。

第 2 行:#include <iostream>
以井号(#)开头的行是由所谓的预处理器读取和解释的指令。它们是在程序本身开始编译之前被解释的特殊行。在这里,指令 #include <iostream> 指示预处理器包含一段名为头文件 iostream 的标准 C++ 代码,该代码允许执行标准的输入和输出操作,例如将本程序的输出(Hello World)写入屏幕。

第 3 行:一个空行。
空行对程序没有影响。它们只是提高了代码的可读性。

第 4 行:int main ()
这一行开始了一个函数的声明。本质上,函数是一组被赋予名称的代码语句:在这里,它将紧随其后的代码语句组命名为“main”。函数将在后面的章节中详细讨论,但基本上,它们的定义由一个类型(int)、一个名称(main)和一对圆括号(())依次构成,括号内可以任选地包含参数。

名为 main 的函数在所有 C++ 程序中都是一个特殊的函数;它是程序运行时被调用的函数。所有 C++ 程序的执行都从 main 函数开始,无论该函数在代码中的实际位置在哪里。

第 5 行和第 7 行:{}
第 5 行的左大括号({)表示 main 函数定义的开始,第 7 行的右大括号(})表示其结束。这两个大括号之间的所有内容都是函数体,它定义了当 main 被调用时会发生什么。所有函数都使用大括号来表示其定义的开始和结束。

第 6 行:std::cout << "Hello World!";
这一行是一个 C++ 语句。语句是可以实际产生某种效果的表达式。它是程序的核心,规定了程序的实际行为。语句按照它们在函数体中出现的顺序执行。

该语句有三个部分:首先,std::cout,它标识了standard)dard)character)output)输出设备(通常是电脑屏幕)。其次,是插入运算符(<<),它表示后面的内容被插入到 std::cout 中。最后,引号内的句子("Hello world!"),是插入到标准输出中的内容。

请注意,该语句以分号(;)结尾。这个字符标志着语句的结束,就像英文中的句号结束一个句子一样。所有 C++ 语句都必须以分号字符结束。C++ 中最常见的语法错误之一就是忘记用分号结束语句。

你可能已经注意到,并非这个程序的所有行在代码执行时都会执行操作。有一行包含注释(以 // 开头)。有一行是给预处理器的指令(以 # 开头)。有一行定义了一个函数(在此例中是 main 函数)。最后,还有一行是以分号结尾的语句(向 cout 插入内容),它位于 main 函数的大括号({ })界定的代码块内。

为了方便人类阅读和理解,该程序被组织成不同的行并进行了适当的缩进。但 C++ 对于缩进或如何将指令拆分到不同行并没有严格的规定。例如,我们本可以写成:

1
2
3
4
int main ()
{
  std::cout << " Hello World!";
}

我们本可以写成:
1
int main () { std::cout << "Hello World!"; }

全部写在一行,这与前面的代码具有完全相同的含义。

在 C++ 中,语句之间的分隔是用结尾的分号(;)来指定的,将其分成不同的行对此目的而言根本不重要。许多语句可以写在一行,或者每个语句可以单独占一行。将代码分成不同的行仅仅是为了让阅读它的人类觉得更易读、更清晰,但对程序的实际行为没有影响。

现在,让我们为我们的第一个程序添加一个额外的语句:

// my second program in C++
#include <iostream>

int main ()
{
  std::cout << "Hello World! ";
  std::cout << "I'm a C++ program";
}
Hello World! I'm a C++ program

在这种情况下,程序在两个不同的语句中向 std::cout 执行了两次插入操作。再次强调,将代码分成不同的行仅仅是为了提高程序的可读性,因为 main 函数完全可以有效地定义成这样:

1
int main () { std::cout << " Hello World! "; std::cout << " I'm a C++ program "; }

源代码也可以被分成更多的代码行:

1
2
3
4
5
6
7
int main ()
{
  std::cout <<
    "Hello World!";
  std::cout
    << "I'm a C++ program";
}

其结果与前面的例子也完全相同。

预处理器指令(以 # 开头的那些)不属于这个通用规则,因为它们不是语句。它们是在正式编译开始之前由预处理器读取和处理的行。预处理器指令必须单独占用一行,并且因为它们不是语句,所以不必以分号(;)结尾。

注释

如上所述,注释不影响程序的操作;然而,它们提供了一个重要的工具,可以直接在源代码中记录程序的功能和运行方式。

C++ 支持两种注释代码的方式:

1
2
// line comment
/* block comment */

第一种,称为行注释,会忽略从双斜杠符号(//)出现处到该行末尾的所有内容。第二种,称为块注释,会忽略从 /* 字符到首次出现的 */ 字符之间的所有内容,并且可以包含多行。

让我们为我们的第二个程序添加注释:

/* my second program in C++
   with more comments */

#include <iostream>

int main ()
{
  std::cout << "Hello World! ";     // prints Hello World!
  std::cout << "I'm a C++ program"; // prints I'm a C++ program
}
Hello World! I'm a C++ program

如果在程序的源代码中包含了注释,但没有使用注释字符组合 ///**/,编译器会把它们当作 C++ 表达式,这极有可能导致编译失败并出现一个或多个错误信息。

使用命名空间 std

如果你以前见过 C++ 代码,你可能见过使用 cout 而不是 std::cout 的情况。两者都指向同一个对象:前者使用其非限定名称cout),而后者则直接在命名空间 std 中对其进行限定(如 std::cout)。

cout 是标准库的一部分,标准 C++ 库中的所有元素都在一个所谓的命名空间(namespace)中声明:即命名空间 std

为了引用 std 命名空间中的元素,程序要么对库中元素的每一次使用都进行限定(就像我们通过在 cout 前加上 std:: 所做的那样),要么引入其组件的可见性。引入这些组件可见性的最典型方式是通过 using 声明

1
using namespace std;

上述声明允许以非限定方式(不带 std:: 前缀)访问 std 命名空间中的所有元素。

考虑到这一点,最后一个例子可以改写为对 cout 进行非限定使用,如下所示:
// my second program in C++
#include <iostream>
using namespace std;

int main ()
{
  cout << "Hello World! ";
  cout << "I'm a C++ program";
}
Hello World! I'm a C++ program

访问 std 命名空间元素的两种方式(显式限定和 using 声明)在 C++ 中都是有效的,并且产生完全相同的行为。为简单起见并提高可读性,这些教程中的示例将更常用后一种带 using 声明的方法,但请注意,显式限定是保证永远不会发生名称冲突的唯一方法。

命名空间将在后面的章节中更详细地解释。
Index
目录