随着程序变得越来越大,出于组织或可重用性目的,通常将它们分成多个文件。使用 IDE 的优点之一是它们使处理多个文件变得更加容易。您已经知道如何创建和编译单文件项目。向现有项目添加新文件非常容易。
当您向项目添加新代码文件时,请为其指定 .cpp 扩展名。
对于 Visual Studio 用户
在 Visual Studio 中,右键单击“解决方案资源管理器”窗口中的“源文件”文件夹(或项目名称),然后选择“添加”>“新项…”。
确保您选择了C++ 文件 (.cpp)。为新文件命名,它将添加到您的项目中。
注意:如果您从“文件”菜单而不是从“解决方案资源管理器”中的项目创建新文件,则新文件不会自动添加到您的项目中。您必须手动将其添加到项目中。为此,请右键单击“解决方案资源管理器”中的“源文件”,选择“添加”>“现有项目”,然后选择您的文件。
现在,当您编译程序时,您应该看到编译器在编译时列出文件的名称。
对于 Code::Blocks 用户
在 Code::Blocks 中,转到“文件”菜单并选择“新建”>“文件…”。
在“从模板新建”对话框中,选择C/C++ 源并单击“执行”。
此时您可能会看到也可能不会看到欢迎使用 C/C++ 源文件向导对话框。如果这样做,请单击“下一步”。
在向导的下一页上,选择“C++”并单击“下一步”。
现在为新文件命名(不要忘记 .cpp 扩展名),然后单击“全部”按钮以确保选择所有构建目标。最后,选择完成。
现在,当您编译程序时,您应该看到编译器在编译时列出文件的名称。
对于 GCC/G++ 用户
从命令行,您可以使用您最喜欢的编辑器自己创建附加文件,并为其命名。编译程序时,您需要在编译行中包含所有相关的代码文件。例如:g++ main.cpp add.cpp -o main,其中main.cpp和add.cpp是代码文件的名称,main是输出文件的名称。
对于 VS Code用户
要创建新文件,请从顶部导航栏中选择“视图”>“资源管理器”以打开“资源管理器”窗格,然后单击项目名称右侧的“新建文件”图标。或者,从顶部导航栏中选择“文件”>“新建文件” 。然后为新文件命名(不要忘记 .cpp 扩展名)。如果该文件出现在.vscode文件夹内,请将其向上拖动一级到项目文件夹。
接下来打开tasks.json文件,并找到行"${file}",
.
您在这里有两个选择:
- 如果您希望明确编译哪些文件,请替换
"${file}",
为您希望编译的每个文件的名称,每行一个,如下所示:
"main.cpp",
"add.cpp",
"${file}",
您可以通过替换为(在 Windows 上)让 VS Code 自动编译目录中的所有 .cpp 文件"${fileDirname}\\**.cpp"
。"${fileDirname}/**.cpp"
在 Unix 上运行。
多文件示例
#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是什么,因为直到第 9 行我们才定义add !我们的解决方案是重新排序函数(将add放在前面)或使用add的前向声明。
现在让我们看一个类似的多文件程序:
add.cpp:
int add(int x, int y)
{
return x + y;
}
main.cpp:
#include <iostream>
int main()
{
std::cout << "The sum of 3 and 4 is: " << add(3, 4) << '\n'; // compile error
return 0;
}
您的编译器可能会先编译add.cpp或main.cpp。无论哪种方式,main.cpp都将无法编译,并给出与前面的示例相同的编译器错误:
main.cpp(5):错误 C3861:“add”:找不到标识符
原因也完全相同:当编译器到达main.cpp的第 5 行时,它不知道标识符add是什么。
请记住,编译器单独编译每个文件。它不知道其他代码文件的内容,也不记得从以前编译的代码文件中看到的任何内容。因此,即使编译器之前可能已经看到了函数add的定义(如果它首先编译了add.cpp),它也不会记住。
这种有限的可见性和短暂的记忆是故意的,原因有两个:
- 当我们更改源文件时,只需重新编译该源文件。
- 在某些情况下,它允许在一个文件中定义函数或变量,而不会与另一文件中相同名称的不同使用发生冲突。
我们的解决方案选项与以前相同:将函数add的定义放在函数main之前,或者通过前向声明满足编译器的要求。在这种情况下,由于函数add位于另一个文件中,因此无法使用重新排序选项。
这里的解决方案是使用前向声明:
main.cpp(带有前向声明):
#include <iostream>
int add(int x, int y); // needed so main.cpp knows that add() is a function defined elsewhere
int main()
{
std::cout << "The sum of 3 and 4 is: " << add(3, 4) << '\n';
return 0;
}
add.cpp(保持不变):
int add(int x, int y)
{
return x + y;
}
现在,当编译器编译main.cpp时,它会知道add标识符是什么并得到满足。链接器会将main.cpp中的add函数调用连接到add.cpp中add函数的定义。
使用这种方法,我们可以让文件访问另一个文件中的函数。
尝试自己编译带有前向声明的add.cpp和main.cpp 。如果出现链接器错误,请确保已将add.cpp正确添加到项目或编译行中。
因为编译器单独编译每个代码文件,所以每个使用std::cout
或std::cin
需要#include <iostream>
.
第一次尝试使用多个文件时,有很多事情可能会出错。如果您尝试上述示例并遇到错误,请检查以下内容:
- 如果您收到有关add未在main中定义的编译器错误,您可能忘记了main.cpp中函数add的前向声明。
- 如果您收到有关add未定义的链接器错误,例如: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 或 Code::Blocks,您应该会看到IDE 左侧或右侧的解决方案资源管理器/项目窗格中列出的add.cpp 。如果没有,请右键单击您的项目,然后添加文件,然后再次尝试编译。如果您在命令行上进行编译,请不要忘记在编译命令中包含main.cpp和add.cpp 。
- 不要从main.cpp中#include “add.cpp”。这将导致预处理器将add.cpp的内容直接插入到main.cpp中,而不是将它们视为单独的文件。
概括
C++ 的设计使得每个源文件都可以独立编译,而无需知道其他文件中的内容。因此,文件实际编译的顺序不应该是相关的。
一旦我们进入面向对象的编程,我们将开始大量使用多个文件,因此现在是确保您了解如何添加和编译多个文件项目的最佳时机。
提醒:每当您创建新的代码 (.cpp) 文件时,您都需要将其添加到您的项目中,以便对其进行编译。
原创文章,作者:jkhxw,如若转载,请注明出处:https://www.jkhxw.com/cpp-programs-with-multiple-code-files/