18

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

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

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

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

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

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
4

5 回答 5

33

将其标记为inline

 inline void globalfunc() { 
 }

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

于 2011-05-21T09:31:18.783 回答
10

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

编辑,解释

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

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

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

于 2011-05-21T09:33:14.453 回答
8

您有 2 个选项:

将其标记为内联,如 nbt 所述,或标记为静态。

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

inline void global_func ()
{
...
}

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

static void global_func ()
{
...
}
于 2013-11-07T02:45:05.910 回答
3

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

所以你可以这样做:

// \file GlobalFunctions.h

namespace  // an un-named namespace
{

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

} // end un named namespace
于 2013-12-19T10:45:07.293 回答
-3
#ifndef SOMESTRING
#define SOMESTRING
... header code
#endif

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

于 2011-05-21T09:35:10.867 回答