包括.cpp文件

我读过像这里这样的地方,你必须包括.h文件,而不是.cpp文件,否则,你会得到一个错误。 所以例如

main.cpp中

#include <iostream> #include "foop.h" int main(int argc, char *argv[]) { int x=42; std::cout << x <<std::endl; std::cout << foo(x) << std::endl; return 0; } 

foop.h

 #ifndef FOOP_H #define FOOP_H int foo(int a); #endif 

foop.cpp

 int foo(int a){ return ++a; } 

工作,但如果我用#include "foop.h"replace#include "foop.cpp"我得到一个错误(使用Dev C ++ 4.9.9.2,Windows):

 multiple definition of foo(int) first defined here 

为什么是这样?

其中include从文件(这是<><>的参数)复制所有内容,所以当预处理程序完成其工作时, main.cpp将如下所示:

 // iostream stuff int foo(int a){ return ++a; } int main(int argc, char *argv[]) { int x=42; std::cout << x <<std::endl; std::cout << foo(x) << std::endl; return 0; } 

所以foo会在main.cpp中定义,但foop.cpp也存在一个定义,所以编译器由于函数重复而“变得困惑”。

阻止包含.cpp文件的原因有很多,但不是严格禁止的。 你的例子应该编译好。

问题可能是你正在编译main.cpp和foop.cpp,这意味着两个foop.cpp副本被链接在一起。 链接器抱怨重复。

这归结为定义声明之间的区别。

  • 您可以多次声明函数和variables,使用不同的翻译单位,也可以使用相同的翻译单位。 一旦你声明了一个函数或一个variables,你可以从这一点使用它。
  • 您可以在所有翻译单元中只定义一次非静态函数或variables。 多次定义非静态项会导致链接器错误。

标题通常包含声明; cpp文件包含定义。 如果多次包含定义文件,则会在链接过程中重复。

在你的情况下,一个定义来自foo.cpp ,另一个定义来自main.cpp ,其中包括foo.cpp

注意:如果您将foo更改为static ,则不会有链接错误。 尽pipe没有错误,但这不是一件好事。

当你说#include "foop.cpp" ,就好像你已经复制了foop.cpp的全部内容并将其粘贴到main.cpp

所以当你编译main.cpp ,编译器会发出一个main.obj ,它包含两个函数的可执行代码: mainfoo

编译foop.cpp本身时,编译器会发出一个foop.obj ,其中包含函数foo的可执行代码。

当你将它们连接在一起时,编译器会看到foo函数的两个定义(一个来自main.obj ,另一个来自foop.obj ),并且抱怨你有多个定义。

因为你的程序现在包含foo函数的两个副本,一个在foo.cpp中,一个在main.cpp中

把#include看作是编译器的指令,将该文件的内容复制/粘贴到你的代码中,所以你最终会得到一个处理过的main.cpp,看起来像这样

 #include <iostream> // actually you'll get the contents of the iostream header here, but I'm not going to include it! int foo(int a){ return ++a; } int main(int argc, char *argv[]) { int x=42; std::cout << x <<std::endl; std::cout << foo(x) << std::endl; return 0; } 

和foo.cpp

 int foo(int a){ return ++a; } 

因此多重​​定义错误

你应该只包含头文件。

如果包含头文件,头文件会自动find.cpp文件。 – >这个过程是由LINKER完成的。

由于一个定义规则 (可能是1 )。

在C ++中,每个非内联对象和函数在程序中必须有一个定义。 通过#include定义foo(int)的文件(CPP文件),它在foop.cpp为#include d的每个文件中以及在foop.cpp本身中定义(假设foop.cpp被编译) 。

你可以使一个函数inline来覆盖这种行为,但我不build议在这里。 我从来没有见过这样的情况: #include一个CPP文件是必要的,甚至是不可取的。

在某些情况下,可能需要包括一些事物的定义。 当您尝试从声明中分离模板的定义时,这是特别正确的。 在这些情况下,我将文件命名为HPP而不是CPP来表示不同之处。


1 :“(可能)”我可能在这里说,因为你发布的实际代码应该编译没有错误,但考虑到编译器错误,您发布的代码似乎可能与您正在编译的代码不完全相同

使用“.h”方法更好但是如果你真的想包含.cpp文件,那么在foo.cpp中使foo(int)是静态的