包括.cpp文件

49 c++

我在这里读过你必须包含.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;
}
Run Code Online (Sandbox Code Playgroud)

foop.h

#ifndef FOOP_H
#define FOOP_H
int foo(int a);
#endif
Run Code Online (Sandbox Code Playgroud)

foop.cpp

int foo(int a){
    return ++a;
}
Run Code Online (Sandbox Code Playgroud)

作品,但如果我更换#include "foop.h"#include "foop.cpp"我得到一个错误(使用开发C++ 4.9.9.2,Windows中):

multiple definition of foo(int)
first defined here
Run Code Online (Sandbox Code Playgroud)

为什么是这样?

xor*_*guy 50

什么include是复制文件中的所有内容(这是<>或者里面的参数""),所以当preproccesor完成它的工作时,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;
}
Run Code Online (Sandbox Code Playgroud)

所以foo将被定义main.cpp,但是定义也存在foop.cpp,因此编译器"混淆"因为函数重复.

  • 我想你可以通过使用 `#pragma once` 指令来解决它。 (2认同)
  • @xorguy foop.c和foop.h如何相互了解?我理解你在答案中说的是什么,但我仍然不清楚main.cpp如何知道foo的定义?main.cpp包含foop.h whare只是声明不定义foo.那么main.cpp如何知道foo的定义呢? (2认同)

Mar*_*som 30

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

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


小智 11

您应该只包含头文件。

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

  • @pasha我曾经读过这个答案并认为它也是正确的......这是错误的并且有点误导。不存在这样的“头文件查找.cpp文件”的事情。因为只有 .cpp 文件被编译。头文件只是停留在那里并等待一些源文件包含它们。查看此视频以了解更多信息 https://www.youtube.com/watch?v=3tIqpEmWMLI (6认同)
  • @pasha这个答案完美地忽略了这个主题的细微差别,同时实际上也是错误的。 (4认同)
  • 这个答案完美地解释了问题中所解决的问题。 (2认同)
  • @enedil 感谢您指出这一点,在花时间在谷歌上之后我现在同意了,但请解释一下为什么会这样,也许我可以学到一些其他东西 (2认同)

rob*_*off 10

当你说#include "foop.cpp",就好像你已经复制了所有内容foop.cpp并将其粘贴进去main.cpp.

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

编译时foop.cpp,编译器会发出foop.obj包含函数可执行代码的内容foo.

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


das*_*ght 6

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

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

标题通常包含声明; cpp文件包含定义.如果包含多次定义的文件,则在链接期间会出现重复项.

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

注意:如果您更改foostatic,则不会出现链接错误.尽管没有错误,但这不是一件好事.