我在像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
这是为什么?
答案 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
,其中包含两个函数的可执行代码:main
和foo
。
编译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