【问题标题】:"Multiple definition of" C++ compiler error“多重定义”C++编译器错误
【发布时间】:2009-03-26 11:53:37
【问题描述】:

我似乎无法在我的一门课程中摆脱这些看似随机的编译错误。 我收到大约 4 个错误,例如:

multiple definition of `draw_line(float, float, float, float)'

multiple definition of `near_far_clip(float, float, float*, float*, float*, float*, float*, float*)'

在方法中间被标记。

我也经常在另一种方法的中间得到multiple definition of `stack'stack 是一个完全不同的文件中的全局变量。我收到错误的文件中甚至都没有提到它。

我尝试将容易出错的文件分成 .h 和 .cpp 文件(最初只是一个 .cpp),但没有任何关于错误的更改...

我没有重复的方法。我只有一个#include 的lines.h 并且开头有一个#ifndef 子句。所有这些错误都出现在 .cpp 文件中。

有什么想法吗?

好的,我得到了代码:

lines.cpp 是我从导师那里收到的转换后的 .c 文件。我包含了 makefile 以防万一,因为我总是遇到问题。我还准确地注释了文件中错误标记的位置,但它们看起来很随机,所以我不知道它是否特别重要。我放弃了 .h 文件,因为它没有解决任何问题或提供帮助。我相信没有它会更容易找到错误。

这里是请求的main.cpp file(没有.h)。


我重新制作了lines.h文件,因为我仍然收到:

multiple definition of `draw_line(float, float, float, float)'

multiple definition of `near_far_clip(float, float, float*, float*, float*, float*, float*, float*)'

lines.cpp 文件中的错误,但 multiple definition of `stack' 错误现在位于 ThreeD.cpp 文件中的随机位置(现在由注释标记)。 更新:此错误已修复,文件已修改为显示:

我搞砸了一些全局变量 extern 的标签,但它似乎没有影响任何东西。

【问题讨论】:

  • 脑海中浮现出许多想法,但如果我要将它们全部列出来,那就太费时间了。毫无疑问,如果我们能看到您的代码,我们会发现更容易缩小问题范围。轻推,轻推,眨眼,眨眼。
  • 你能展示你最后的 g++ 命令吗?
  • 你还想要什么代码?

标签: c++ linker


【解决方案1】:

您可能会将函数定义包含在头文件中。包括 inline 关键字,这样它们就不会被每个目标文件导出。或者,将函数放在它们自己的 .cpp 文件中。

对于您的全局变量,您需要在头文件中使用extern 关键字。否则,每个目标文件都会导出它们自己的变量,链接器会混淆哪个是正确的。

【讨论】:

    【解决方案2】:

    为什么要在 ThreeD.cpp 中#includelines.cpp?这很不寻常。

    你的makefile 需要lines.o,所以你要编译lines.cpp。在lines.cpp 中定义的任何内容都将在lines.o 和ThreeD.o 中。

    lines.cpp 中有一个有趣的注释:

    Don't forget to put declarations in your .h files. 
    

    我认为讲师希望您将 lines.cpp 分解为 .h 和 .cpp。

    摘自lines.cpp:

    /* These go in your .h file or in lines.h */
    /*
    
    Line drawing header.
    
    */
    
    
    void draw_line(float, float, float, float);
    int near_far_clip(float, float, float *, float *, float *, float *,
                      float *, float *);
    

    我怀疑这两个声明应该是lines.h中唯一的东西。

    【讨论】:

    • 所以我可以使用lines.cpp的方法,我在ThreeD.h中有它,但我正在移动它以查看是否有任何区别。当它在 .h 文件中时,我得到了更多的错误,但它们都是相同的类型。这有关系吗?
    • 是的,这很重要。将lines.cpp分成一个.h文件和一个.cpp文件,然后#include onlylines.h in ThreeD.cpp。
    • 我事先已经这样做了。我收到了完全相同的错误,因此我将其恢复为原始状态。我应该对 makefile 进行任何更改(关于您对lines.o 和 ThreeD.o 中定义的lines.cpp 的评论?)
    • 您可以将lines.o 从makefile 中取出,但它是一个杂项。正确的做法是将lines.cpp分解成lines.h和lines.cpp,其中lines.h只有你在ThreeD中使用的函数的声明。
    • 不客气。现在出去给我们画一些很棒的盒子!
    【解决方案3】:

    请发布一些代码 sn-ps。也许你在类声明和外部定义你的方法?

    class X {
        void foo();    // No definition, just declaration
        void bar() {}  // Declaration + definition
    };
    
    void X::foo() {}    // First Definition, OK
    void X::bar() {}    // Already defined, ERROR
    

    【讨论】:

      【解决方案4】:

      如前所述 - 这里没有足够的信息来正确诊断。

      但是,如果 draw_line 等是在头文件中而不是在源 (cpp) 文件中定义的,那么您可能有一些在头文件中被声明为内联的方法,但实际上并没有正确内联。在这种情况下,每个包含标头的 .cpp 文件都会生成它们自己的 draw_line 函数定义,并在链接时生成警告。

      如果您使用来自已被遗忘或删除的系统标头的 #defined INLINE 宏,并且无论出于何种原因,该 INLINE 会被预处理为空,就会发生这种情况。

      例如:

      //Lines.h
      
      #define GCCC //Note the typo
      
      #if defined(GCC)
      #define INLINE inline
      #elif defined (MSVC)
      #define INLINE __inline
      #else
      
      #define INLINE //Due to the typo, INLINE will be turned into nothing
      #endif
      
      INLINE void draw_line(float x1, float y1, float x2, float y2)
      {
         //Draw the line
      }
      
      //File1.cpp
      #include "lines.h" //will define draw_line
      
      //File2.cpp
      #include "lines.h" //will also define draw_line
      

      并且链接 File1.cpp 和 File2.cpp 会产生多个声明错误

      【讨论】:

        【解决方案5】:

        检查是否包含拼写错误。
        检查您的制作选项,也许有人编译成多个目标文件。
        尝试排除部分文件和代码,直到找不到错误原因。

        已编辑:
        修复包含 *.cpp 文件。它们应该是链接的。

        【讨论】:

        • 你到底是什么意思?您是在谈论 makefile 还是 .h/.cpp 文件之一?
        • 您在 ThreeD.cpp 中有 #include "lines.cpp" - 这与 lines.cpp 中的所有代码都复制粘贴在 ThreeD.cpp 中相同 - 具有功能定义。还有lines.cpp - 具有相同功能的分离编译实体。它会导致链接器错误。
        • 创建lines.h,在lines中插入这些函数的声明,并包含这个lines.h
        • 我相信我按照你说的做了,但我仍然遇到同样的错误。我更新了代码
        • 另一个问题! ThreeD.cpp 和 main.cpp 中都有全局变量堆栈。将此变量定义为静态变量。
        【解决方案6】:
        #ifndef THREED_H_
        #define THREED_H_
        #endif /* THREED_H_ */
        

        删除或评论这些行,这对我有用

        【讨论】:

          【解决方案7】:

          多个定义错误是链接器错误,但如果没有更多信息,就很难诊断它们。检查同一个文件在链接器命令中没有出现两次,并且你的头文件只包含声明,没有定义。

          【讨论】:

            【解决方案8】:

            没有看到代码真的没有帮助你。编译器清楚地声称与您相反(有 is 至少有一个重复的定义)。

            尝试用最简单的例子重现错误。您是否尝试过在命令行中在 Eclipse 之外编译代码?结果如何?

            【讨论】:

            • 一个很好的答案,@KR,但我没有看到问题中提到 Eclipse。
            • @Pax,它在原始问题中。我编辑了它,因为它似乎对问题不太重要(标题中唯一提到 Eclipse)。
            • 啊。我必须记得在打开陷阱之前检查历史记录:-)
            【解决方案9】:

            嗨,我在这里看到的基本规则适用于 ll。我将解释这些错误是如何工作的,以及这些错误是怎么回事: 让我们举一个例子 “制作一个全局变量”

            不要混淆头文件,对于 cpp 文件。 标题只是为了允许多个文件项目有一个共同的 界面 在链接之前。

            1.列表项

            您应该在标题中提供有关全局变量的信息:

            extern int Var_Global;

            1. 列表项

              while keeping the Actual code in the
              cpp :
              
              int Var_Global;
              

            并确保您 1. 包含标题,以及 2. 链接代码。

            链接代码一次,而且只有一次,数据只有一个副本, 但是您可以整天包含标题,这会告诉其他代码 链接时会有数据的副本。

            我看到很多人将代码放在头文件中,而这可能适用于 在某些情况下,这是一个坏习惯,并且会很快引起问题或 稍后。

            问候,

            普拉桑塔

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2016-07-13
              • 2010-09-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多