我刚刚开始学习C ++,无法理解我需要如何使用头文件。我已经看到并阅读了一些关于Stack Overflow的现有答案,但仍然无法理解。我写了这段代码,它给了我Unresolved Externals错误。
Sum.h
#ifndef SUM
#define SUM
int add(int x, int y, int z);
#endif
Sum.cpp
#include <iostream>
#include "Sum.h"
int add(int x, int y, int z)
{
return x + y + z;
}
Main.cpp的
#include <iostream>
#include "Sum.h"
int main()
{
using namespace std;
cout << "3 + 4 + 5 = " << add(3, 4, 5) << endl;
return 0;
}
如何解决此问题,以便我的代码可以运行?
谢谢!
编辑:忘记添加,我正在使用Microsoft Visual Studio Express 2013 for Windows Desktop。
答案 0 :(得分:3)
我假设您正在尝试运行这样的程序:
g++ main.cpp
./a.out
问题是,即使你的程序会编译,它也不会链接&#34;。发生的事情是链接器无法找到&#34; add(int,int,int)&#34;的代码。要解决此问题,您需要指定编译中的所有文件。试试这个:
g++ main.cpp sum.cpp
./a.out
在第一种情况下,虽然您的sum.h
文件是直接包含的,但是有一个预处理器规范要求导入它。然后,main.cpp
编译,但输出不包含add
函数的代码。输出只是说&#34;在这些数字上调用一个名为add的函数&#34;。编译器告诉链接器,当最终将函数全部转换为可执行文件时,链接器负责找到该函数。然后当链接器运行时,它无法找到任何方法&#34;添加&#34;其中&#34; main.cpp&#34;的输出指的是。结果,它会抛出错误。
在第二种情况下,两个文件都被编译(通常是.o文件),其中包含其中包含的所有文件的代码。现在,当链接器尝试将其全部链接时,它可以轻松找到add
方法,因为它具有要使用的.o文件。试试这个可以帮助您了解此过程的工作原理:
g++ -c main.cpp
这会将main.cpp编译为main.o
文件。在目录中执行ls
以查看此文件。 -c
选项要求编译器跳过链接过程并仅编译源文件。然后,这样做:
g++ -c sum.cpp
如果你再看看,你会发现有一个名为sum.o
的文件。因此,您基本上已将文本中的代码转换为二进制,这是一种中间格式。大多数验证,类型检查,语法检查等已经执行,main.o
和sum.o
是有效的文件,表示执行某个计算的步骤。请注意,编译步骤不需要main
方法。它只是将指令从一种格式转换为另一种格式。在构建可执行文件时需要它,因为您当然需要知道在运行可执行文件时应该执行什么。要获得最终的可执行文件,您只需要执行此操作:
g++ -o myexec.out sum.o
哎呀..你在这里看到一个错误。它说什么? undefined reference to main
。这证实了我们之前的想法,当我们说链接器需要一个&#34; main&#34;链接到的函数,否则它不知道运行可执行文件时从哪里开始。让我们给它一个主要功能:
g++ -o myexec.out sum.o main.o
而且..你去..编译。 -o
开关只是告诉g++
应该调用输出可执行文件。要运行您的程序,只需执行以下操作:
./myexec.out
这就是全部......一旦你对此感到满意,你就想进入Makefile和autotools。现实生活中的项目有成千上万个C ++文件,这些文件以类似的方式编译,但是一旦你进入两位数的文件编号就很难管理。因此,我们使用make
之类的工具来简化此过程并使其具有高度可配置性。希望这有助于您开始!
修改#2 强>
我以为我会很快放弃对.h文件的需求。编译器一次只处理文件。因此,当它处理main.cpp时,它遇到了一个名为add(4, 5, 1)
的东西,它不知道add
是什么。据它所知,它可能是一个变量int add = 10
而我会错误地使用它。编译器如何验证这一点? sum.h文件可以帮助它,并在此过程中帮助我们。 .h
文件只告诉编译器符号add
是什么类型。如果您尝试创建另一个名为sum2.cpp
的文件,并在其中定义添加为add(int x, int y)
而不是3变量函数,则两个文件都将编译文件,但链接仍将失败。这是因为链接器正在寻找符号add(int, int, int)
,而它看到的是add(int, int)
。编译器只根据你抛出的定义来验证你的代码。
如果您要从第一行删除#include "sum.h"
语句,只需将其替换为int add(int x, int y, int z);
,并按照上面所述的所有步骤操作,它仍然有效。但是,我们在单独的文件中定义它的原因是我们更容易管理变更。在这种情况下,即使sum.cpp和main.cpp分别进行编译,它们也是根据相同的定义进行编译的,这使我们都得到了检查。只有一个定义的位置,它充当了真理的来源,并确保sum.cpp和main.cpp都是同步的。