【问题标题】:C++: Multiple definition error for global functions in the header fileC++:头文件中全局函数的多重定义错误
【发布时间】:2011-08-30 03:59:18
【问题描述】:

这个函数是全局的,定义在头文件中(暂时我想保留在那里)。

头文件还构成一个具有内联函数的特定类,其中一个函数调用 this 全局函数。

源文件不包含任何出现问题的全局函数。

关于错误原因的任何提示?

如果有人感兴趣,我可以发布代码。

mainwindow.o: In function `tileForCoordinate(double, double, int)':
mainwindow.cpp:(.text+0x310): multiple definition of `tileForCoordinate(double, double, int)'
main.o:main.cpp:(.text+0xd0): first defined here
moc_mainwindow.o: In function `qHash(QPoint const&)':
moc_mainwindow.cpp:(.text+0x0): multiple definition of `qHash(QPoint const&)'
main.o:main.cpp:(.text+0x0): first defined here
moc_mainwindow.o: In function `tileForCoordinate(double, double, int)':
moc_mainwindow.cpp:(.text+0x150): multiple definition of `tileForCoordinate(double, double, int)'
main.o:main.cpp:(.text+0xd0): first defined here
collect2: ld returned 1 exit status
make: *** [SimpleRouting] Error 1

【问题讨论】:

    标签: c++ qt multiple-definition-error


    【解决方案1】:

    你有两个选择:

    按照 nbt 的说明将其标记为内联或静态。

    inline 将从源中获取全局函数的实现并将其复制到调用函数的任何位置。

    inline void global_func ()
    {
    ...
    }
    

    static 将告诉链接器不要将代码复制到新的目标文件中,而只是在原始文件中引用它。

    static void global_func ()
    {
    ...
    }
    

    【讨论】:

      【解决方案2】:

      对于在头文件中定义的全局函数,在未命名的命名空间中声明它应该/也可以工作。根据 Deitel 的 C++ How to Program,在 C++ 中,未命名的命名空间比静态命名空间更可取。

      所以你可以这样做:

      // \file GlobalFunctions.h
      
      namespace  // an un-named namespace
      {
      
      void GlobalFunctionOne() {...implementation...}
      
      } // end un named namespace
      

      【讨论】:

        【解决方案3】:

        如果您在头文件中放置一个函数,它将为每个包含导致重复的头文件的 c/cpp 文件生成。使其内联会有所帮助。

        编辑、解释

        作为#ifndef、#define ... #endif 构造的标题保护通常被称为仅防止在单个cpp 文件中重复和递归包含。这与源文件包含标头 A 和 B 且 B 也包含 A 的情况相关。如果 A 还包含 B,则会发生递归包含。

        您的问题出现是因为您有多个 .cpp 文件。在编译一个 cpp 期间,编译器不知道其他 cpp 文件的存在。

        请注意,#include、#ifdef 和朋友都是预处理器指令。在编译之前对源文件进行预处理(认为它通常被视为编译过程的一部分)。预处理器基本上是一个文本处理器。例如,#include 在文本上被替换为头文件的内容。从代码中删除评估为 false 的 #ifdefs 的内容。实际的编译器会得到一个由 cpp 和所有引用的包含文件组成的大文件,并将其转换为目标文件。

        【讨论】:

        • 但后来我在 .h 文件的顶部写了 #ifndef MAINWINDOW_H #define MAINWINDOW_H。这不应该有帮助吗?
        • 编辑我的答案来解释你的问题
        【解决方案4】:
        #ifndef SOMESTRING
        #define SOMESTRING
        ... header code
        #endif
        

        标题的代码只会在第一次包含。

        【讨论】:

        • 错了。它将包含在使用它的每个翻译单元中,这就是导致多个定义错误的原因。包含守卫仅防止在同一翻译单元中多次包含。
        • 这个我知道,我已经将它包含在.h中但仍然存在错误,所以我创建了这个线程。
        【解决方案5】:

        标记为inline:

         inline void globalfunc() { 
         }
        

        虽然这样做意味着它不再是严格意义上的全局 - 您将在每个使用标头的翻译单元中获得一个副本,但链接器不会对此表示反对。

        【讨论】:

        • 非常感谢你,你在点。现在请麻烦解释一下为什么需要将 .h 文件中定义的全局函数内联附加?或者,如果您有合适的链接,请分享。
        • @Anisha 如果您不这样做,编译器会生成具有外部链接的函数,这意味着链接器会看到多个具有相同名称的函数并抱怨。将其标记为内联会为其提供本地(基本上是文件范围)链接,因此链接器会将多个函数视为不同。
        • 谢谢,现在我必须用谷歌搜索更多关于外部链接的信息。
        • @Anisha:当你可以在 SO 中找到它时需要谷歌 :) 。如果有帮助,请检查问题及其答案 :: stackoverflow.com/questions/1358400/…
        • 当你在头部定义模板函数时为什么不会发生这种情况(这很常见)?并且:我认为包含警卫是为了防止多个定义/声明?!
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-29
        • 1970-01-01
        • 2021-04-28
        • 2021-03-11
        相关资源
        最近更新 更多