多代码文件程序
本节阅读量:将文件添加到项目中
随着程序越来越大,为了更好地组织代码或提高可重用性,通常会将其拆分为多个文件。使用IDE的优点之一是处理多个文件更加容易。之前已经讲解了创建和编译单文件项目,将新文件添加到现有项目也非常简单。
最佳实践
将新代码文件添加到项目中时,使用扩展名.cpp。
在Visual Studio中,右键单击“解决方案资源管理器”窗口中的“源文件”文件夹(或项目名称),然后选择“添加”>“新建项”。
确保已选择C++文件(.cpp)。指定新文件的名称,即可添加到项目中。
注意:如果从”文件”菜单而不是从解决方案资源管理器中的项目创建新文件,新文件不会自动添加到项目中。必须手动将其添加到项目中。操作方法是在解决方案资源管理器中右键单击源文件,选择添加>现有项,然后选择对应文件。
现在,当编译程序时,会看到编译器在编译文件时列出了文件的名称。
对于GCC/G++用户
从命令行中,可以使用您喜爱的编辑器自己创建附加文件,并为其命名。编译程序时,需要在命令中包含所有相关的代码文件。例如:g++ main.cpp add.cpp -o main,其中main.cpp和add.cpp是代码文件的名称,main是输出文件的名称。
多文件示例
在前向声明一节中,有一个无法编译的单个文件程序:
|
|
当编译器在main的第5行到达add的函数调用时,不知道add是什么,因为add直到第9行才定义!解决方案是要么重新排序函数(将add放在前面),要么使用前向声明。
下面是一个类似的多文件程序:
add.cpp:
|
|
main.cpp:
|
|
编译器可以先编译add.cpp或main.cpp。无论哪种方式,main.cpp都将无法编译,给出与上一示例相同的编译器错误:
原因也完全相同:当编译器到达main.cpp的第5行时,它不知道add是什么。
请记住,编译器是单独编译每个文件的。它不知道其他代码文件的内容,也不记得从之前编译的其他代码文件中看到的内容。因此,即使编译器之前见过函数add的定义(如果先编译了add.cpp),也不会记住。
这种有限的可见性和短暂的记忆是有意设计的,原因有三:
- 一个项目中的多个文件可以按任意顺序编译。
- 如果修改了单个文件,只有修改过的文件需要重新编译。
- 减少了不同文件之间发生命名冲突的概率。
下一课中,将探索名称发生冲突时会发生什么。
解决方案与前面相同:将函数add的定义放在函数main之前,或者使用前向声明。由于函数add位于另一个文件中,重新排序是不可行的。
解决方案是使用前向声明:
main.cpp(带前向声明):
|
|
add.cpp(保持不变):
|
|
现在,当编译器编译main.cpp时,它将知道add()是什么。链接器会把main.cpp中对add()的函数调用连接到add.cpp中的函数定义。
使用这种方法,可以让文件访问另一个文件中的函数。
尝试使用前向声明编译add.cpp和main.cpp。如果有链接器错误,请确保已将add.cpp正确添加到项目或编译命令中。
提示
由于编译器单独编译每个代码文件(然后忘记它看到的内容),因此使用std::cout或std:∶cin的每个代码文件都需要 #include <iostream>。
上面示例中,如果add.cpp使用了std::cout或std:∶cin,则需要 #include <iostream>。
关键点
在表达式中使用标识符时,标识符必须能链接到定义。
- 如果编译器尚未看到正在编译的文件中标识符的前向声明或定义,会在使用标识符的位置报错。
- 如果同一文件中存在定义,编译器会把标识符的使用连接到定义。
- 否则,如果定义存在于不同文件中(并且对链接器可见),则链接器会把标识符的链接连接到定义。
- 否则,链接器报出错。
遇到错误时解决方法
第一次尝试使用多个文件时,有许多可能会出错的地方。如果尝试上述示例并遇到错误,请检查以下内容:
- 如果编译器报错main中没有定义add,那么可能是忘记在main.cpp中前向声明add函数。
- 如果有如下链接错误
|
|
最有可能的原因是add.cpp没有正确添加到项目中。编译时,你会看到编译器列出main.cpp和add.cpp。如果只看到main.cpp,说明add.cpp没有被编译。如果使用Visual Studio,则应在IDE的解决方案资源管理器/项目窗格中看到列出的add.cpp。如果没有,请右键单击项目并添加文件,然后再尝试编译。如果在命令行上编译,不要忘记在编译命令中同时包含main.cpp和add.cpp。
或者是将add.cpp添加到了错误的项目中。
或者是文件被设置为不编译或不链接。检查文件属性,确保文件被配置为参与编译/链接。在Visual Studio中,有”从生成中排除”选项,应设置为”否”或保留为空。
- 不要在main.cpp中添加"#include add.cpp"。后面预处理器章节会解释原因。
总结
C++的设计使得每个源文件都可以独立编译,而不需要知道其他文件中的内容。因此,文件的实际编译顺序不重要。
一旦进入面向对象编程阶段,会开始大量处理多个文件,因此现在是确保了解如何添加和编译多文件项目的好时机。
提醒:无论何时创建新的代码(.cpp)文件,都需要添加到项目中,以便进行编译。