包括.cpp文件

时间:2013-10-23 16:21:39

标签: c++

我在像here这样的地方读过你必须包含.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"替换#include "foop.cpp",我会收到错误(使用Dev C ++ 4.9.9.2,Windows):

multiple definition of foo(int)
first defined here

这是为什么?

9 个答案:

答案 0 :(得分:43)

include所做的是复制文件中的所有内容(这是<>""中的参数),因此当preproccesor完成其工作时{{1}看起来像是:

main.cpp

所以foo将在// 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; } 中定义,但main.cpp中也存在定义,因此编译器会因为函数重复而“混淆”。

答案 1 :(得分:28)

有许多理由不鼓励包含.cpp文件,但并不严格禁止使用.cpp文件。你的例子应该编译得很好。

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

答案 2 :(得分:9)

当您说#include "foop.cpp"时,就好像您复制了foop.cpp的全部内容并将其粘贴到main.cpp中一样。

因此,当您编译main.cpp时,编译器会发出main.obj,其中包含两个函数的可执行代码:mainfoo

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

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

答案 3 :(得分:5)

这归结为定义声明之间的差异。

  • 您可以多次声明函数和变量,在不同的翻译单元中,或在同一翻译单元中。一旦声明了函数或变量,就可以从那时开始使用它。
  • 您可以在所有翻译单元中仅定义一次非静态函数或变量。多次定义非静态项会导致链接器错误。

标题通常包含声明; cpp文件包含定义。当您包含多次定义的文件时,您会在链接期间获得重复项。

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

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

答案 4 :(得分:2)

您应该只包含头文件。

如果包含头文件,头文件会自动查找.cpp文件。   - &GT;此过程由LINKER完成。

答案 5 :(得分:1)

因为你的程序现在包含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;
}

因此多重定义错误

答案 6 :(得分:1)

由于One Definition Rule(可能是 1 )。

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

您可以创建一个函数inline来覆盖此行为,但我不建议这样做。我从未见过#include CPP文件是必要的甚至是可取的情况。

在某些情况下,需要包含某些内容的定义。当您尝试从模板的声明中分离模板的定义时,尤其如此。在这些情况下,我将文件命名为HPP而不是CPP来表示差异。


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

答案 7 :(得分:0)

所以我发现,如果您是从Visual Studios进行编译,则只需从最终版本(扩展源)中排除包含的.cpp文件:

  

Visual Studios:.cpp文件>右键单击>属性>配置属性>   常规>从构建中排除>

我相信您也可以在从命令行进行编译时排除文件。

答案 8 :(得分:-1)

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

中创建foo(int)static