简体   繁体   English

C ++:头文件中全局函数的多个定义错误

[英]C++: Multiple definition error for global functions in the header file

This function is global and is defined in the header file ( temporarily I want to keep it there). 此函数是全局的,并在头文件中定义( 暂时我想将其保留在那里)。

The header file also constitutes a particular class which has inline functions and one of those functions call this global function. 头文件也构成一个具有内联函数的特定类,其中一个函数调用全局函数。

The source file doesn't contain any occurrences of the global function in question. 源文件不包含任何有问题的全局函数。

Any hints on cause of the error? 有关错误原因的任何提示?

I can post the code if anyone is interested. 如果有人有兴趣,我可以发布代码。

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

mark it as inline : 将其标记为inline

 inline void globalfunc() { 
 }

although doing so means that it will no longer strictly be global - you will get a copy in each translation unit that uses the header, but the linker won't object to this. 虽然这样做意味着它将不再严格地是全局的 - 您将在每个使用标头的翻译单元中获得副本,但链接器不会反对此。

If you put a function in the header it will be generated for each c/cpp file that includes that header leading to duplicates. 如果在头文件中放入一个函数,它将为每个包含该头文件的c / cpp文件生成,从而导致重复。 Making it inline will help. 使其内联将有所帮助。

Edit, explanation 编辑,解释

Header guards as the #ifndef, #define ... #endif construction is often called only prevent double and recursive inclusion in a single cpp file. 标题守卫作为#ifndef,#define ... #endif构造通常被调用,仅防止在单个cpp文件中包含双重和递归。 This is relevant in the case where a source file includes headers A and B and B also includes A. Recursive inclusion would happen if A also included B. 这与源文件包含标题A和B以及B还包括A的情况相关。如果A也包括B,则会发生递归包含。

Your problem arises because you have multiple .cpp files. 您的问题出现是因为您有多个.cpp文件。 During compilation of one cpp the compiler doesn't know about the existence of the other cpp files. 在编译一个cpp期间,编译器不知道其他cpp文件的存在。

Notice that #include, #ifdef and friends are preprocessor directives. 请注意,#include,#iff和friends是预处理程序指令。 Preprocessing happens on source files before compilation (thought it is often regarded and done as part of the compilation process). 在编译之前对源文件进行预处理(认为它通常被视为编译过程的一部分)。 The preprocessor basically is a text processor. 预处理器基本上是文本处理器。 For instance an #include is textually replaced with the contents of the header file. 例如,#include在文本上被替换为头文件的内容。 Contents of #ifdefs that evaluate to false are removed from the code. 评估为false的#ifdefs的内容将从代码中删除。 The actual compiler gets one single big file consisting of the cpp and all referenced include files which it translates into an object file. 实际的编译器获取一个由cpp和所有引用的包含文件组成的大文件,它将它转换为目标文件。

You have 2 options: 你有2个选择:

Mark it as inline, as explained by nbt, or as static. 将其标记为内联,如nbt所述,或静态。

inline will take the implementation of the global function from the source and copy it into wherever the function is called. inline将从源代码中执行全局函数,并将其复制到函数调用的任何位置。

inline void global_func ()
{
...
}

static will tell the linker to not copy the code into the new object file but rather only reference it in the original. static将告诉链接器不要将代码复制到新的目标文件中,而只是在原始文件中引用它。

static void global_func ()
{
...
}

For a global function defined in a header file, declaring it within an un-named namespace should/will also work. 对于头文件中定义的全局函数,在未命名的命名空间中声明它应该/也可以。 According to C++ How to Program by Deitel, in C++ an unnamed namespace is preferable to static. 根据Dexel的C ++ How to Program,在C ++中,一个未命名的命名空间比静态更好。

So you could do this: 所以你可以这样做:

// \file GlobalFunctions.h

namespace  // an un-named namespace
{

void GlobalFunctionOne() {...implementation...}

} // end un named namespace
#ifndef SOMESTRING
#define SOMESTRING
... header code
#endif

The code of the header will only be included the first time. 标题的代码将仅在第一次包含。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM