......的多个定义C ++

时间:2015-03-30 23:02:57

标签: c++ linker object-files

这是一个有点理论上的问题......

我一直在阅读链接目标文件。现在我收到有关某些函数的多个定义的错误消息。我相信已将问题确定如下:

  • 我有两个单独的头文件A和B.

  • 两个标题都访问相同的标题H.

  • 从A和B我编译了目标文件AO和BO。

  • 当我尝试通过将AO和BO链接到M来编译包含A和B的cpp-File M时,我收到有关多个定义的错误消息。

  • 错误信息所涉及的功能位于H.

我认为问题是,AO和BO在某种程度上都是H的引用或编译代码,因此当我在编译M时链接AO ad BO时它会出现两次。我是否正确识别了问题,或者我是我可能错过了一些东西?

如果是这样,你如何避免或解决这个问题?

编辑:我说我编译了头文件。对不起,这是说话的草率方式。我使用头文件A和B中的类方法的实现编译了cpp文件。

3 个答案:

答案 0 :(得分:1)

您永远不应该编译.h(标题)文件。 头文件是一个C ++源文件,它通过#include指令包含在其他C ++源文件中。

您应编译的唯一文件是.cpp个文件,通常称为实施文件

在头文件中不包含函数定义也很重要。每个函数定义只能编译一次,因此必须编码为一个实现文件。头文件应仅包含:

  • 前瞻性声明
  • 其他#include s
  • 类型
  • 实习医生
  • 模板代码
  • 功能原型

您的问题的原因很可能是您在H文件中包含了一个完整的函数定义,因此,当您编译A和B实现文件时(它们应该被称为实现文件,如果您正在编译它们;或者,您可以考虑将这些头文件中的函数定义移动到单独的实现文件中,并且只编译那些实现文件),该函数被编译为AO和BO对象文件。这就是链接失败的原因;函数在链接时被多次定义。

要解决此问题,您需要将H头文件中的任何函数定义移动到单独的实现文件中。由于H似乎与您已经拥有的任何单个实现文件无关(我说这是因为它似乎是A和B的依赖),因此将这些函数定义移动到新的H中可能是最有意义的。 cpp实现文件。作为构建过程的一部分,您将必须构建H.cpp,并在链接时将其链接到最终的可执行文件。

答案 1 :(得分:0)

您是否记得头文件中的标题保护,否则您最终会遇到此问题。

#ifndef MY_HEADER_H_INC
#define MY_HEADER_H_INC

/* Put Header Code Here */

#endif // MY_HEADER_H_INC

您最终会多次包含同一个文件,因为正如您所说的那样,两者都包含标题H,那么您可以包括每个文件。这听起来像是最可能的原因。

答案 2 :(得分:0)

在C ++中,您应该将声明与实现分开,以避免重新定义(如您所描述的情况)。将声明放入头文件filename.h中,其中包含一些include guard(基于#define或#pragma一次);将您的定义放在filename.cpp中,其中包括#include" filename.h"的标题。编译时,只编译.cpp文件;不要尝试编译头文件(除非你需要一个预编译的头文件,你可能不需要)。