章节目录

多代码文件程序

本节阅读量:

将文件添加到项目中

随着程序越来越大,为了更好地组织代码或提高可重用性,通常会将其拆分为多个文件。使用IDE的优点之一是处理多个文件更加容易。之前已经讲解了创建和编译单文件项目,将新文件添加到现有项目也非常简单。

在Visual Studio中,右键单击“解决方案资源管理器”窗口中的“源文件”文件夹(或项目名称),然后选择“添加”>“新建项”。

新建项

确保已选择C++文件(.cpp)。指定新文件的名称,即可添加到项目中。

新建文件

注意:如果从”文件”菜单而不是从解决方案资源管理器中的项目创建新文件,新文件不会自动添加到项目中。必须手动将其添加到项目中。操作方法是在解决方案资源管理器中右键单击源文件,选择添加>现有项,然后选择对应文件。

现在,当编译程序时,会看到编译器在编译文件时列出了文件的名称。

多文件示例

在前向声明一节中,有一个无法编译的单个文件程序:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <iostream>

int main()
{
    std::cout << "The sum of 3 and 4 is: " << add(3, 4) << '\n';
    return 0;
}

int add(int x, int y)
{
    return x + y;
}

当编译器在main的第5行到达add的函数调用时,不知道add是什么,因为add直到第9行才定义!解决方案是要么重新排序函数(将add放在前面),要么使用前向声明。

下面是一个类似的多文件程序:

add.cpp:

1
2
3
4
int add(int x, int y)
{
    return x + y;
}

main.cpp:

1
2
3
4
5
6
7
#include <iostream>

int main()
{
    std::cout << "The sum of 3 and 4 is: " << add(3, 4) << '\n'; // 编译失败
    return 0;
}

编译器可以先编译add.cpp或main.cpp。无论哪种方式,main.cpp都将无法编译,给出与上一示例相同的编译器错误:

原因也完全相同:当编译器到达main.cpp的第5行时,它不知道add是什么。

请记住,编译器是单独编译每个文件的。它不知道其他代码文件的内容,也不记得从之前编译的其他代码文件中看到的内容。因此,即使编译器之前见过函数add的定义(如果先编译了add.cpp),也不会记住。

这种有限的可见性和短暂的记忆是有意设计的,原因有三:

  1. 一个项目中的多个文件可以按任意顺序编译。
  2. 如果修改了单个文件,只有修改过的文件需要重新编译。
  3. 减少了不同文件之间发生命名冲突的概率。

下一课中,将探索名称发生冲突时会发生什么。

解决方案与前面相同:将函数add的定义放在函数main之前,或者使用前向声明。由于函数add位于另一个文件中,重新排序是不可行的。

解决方案是使用前向声明:

main.cpp(带前向声明):

1
2
3
4
5
6
7
8
9
#include <iostream>

int add(int x, int y); // 让 main.cpp 知道 add() 是在其它地方定义的函数

int main()
{
    std::cout << "The sum of 3 and 4 is: " << add(3, 4) << '\n';
    return 0;
}

add.cpp(保持不变):

1
2
3
4
int add(int x, int y)
{
    return x + y;
}

现在,当编译器编译main.cpp时,它将知道add()是什么。链接器会把main.cpp中对add()的函数调用连接到add.cpp中的函数定义。

使用这种方法,可以让文件访问另一个文件中的函数。

尝试使用前向声明编译add.cpp和main.cpp。如果有链接器错误,请确保已将add.cpp正确添加到项目或编译命令中。


遇到错误时解决方法

第一次尝试使用多个文件时,有许多可能会出错的地方。如果尝试上述示例并遇到错误,请检查以下内容:

  1. 如果编译器报错main中没有定义add,那么可能是忘记在main.cpp中前向声明add函数。
  2. 如果有如下链接错误
1
unresolved external symbol "int __cdecl add(int,int)" (?add@@YAHHH@Z) referenced in function _main

最有可能的原因是add.cpp没有正确添加到项目中。编译时,你会看到编译器列出main.cpp和add.cpp。如果只看到main.cpp,说明add.cpp没有被编译。如果使用Visual Studio,则应在IDE的解决方案资源管理器/项目窗格中看到列出的add.cpp。如果没有,请右键单击项目并添加文件,然后再尝试编译。如果在命令行上编译,不要忘记在编译命令中同时包含main.cpp和add.cpp。

或者是将add.cpp添加到了错误的项目中。

或者是文件被设置为不编译或不链接。检查文件属性,确保文件被配置为参与编译/链接。在Visual Studio中,有”从生成中排除”选项,应设置为”否”或保留为空。

  1. 不要在main.cpp中添加"#include add.cpp"。后面预处理器章节会解释原因。

总结

C++的设计使得每个源文件都可以独立编译,而不需要知道其他文件中的内容。因此,文件的实际编译顺序不重要。

一旦进入面向对象编程阶段,会开始大量处理多个文件,因此现在是确保了解如何添加和编译多文件项目的好时机。

提醒:无论何时创建新的代码(.cpp)文件,都需要添加到项目中,以便进行编译。


2.6 前向声明

上一节

2.8 命名冲突和名称空间简介

下一节