如何查找函数的多个定义

发布于 2024-11-09 09:27:35 字数 777 浏览 6 评论 0原文

我写了一个 findDialog 来查找搜索的文本。当我给出 make 命令时,它返回

g++ -Wl,-O1 -o findDialog FindDialog.o main.o moc_FindDialog.o    -L/usr/lib -lQtGui -lQtCore -lpthread 
moc_FindDialog.o: In function `FindDialog::findClicked()':
moc_FindDialog.cpp:(.text+0x20): multiple definition of `FindDialog::findClicked()'
FindDialog.o:FindDialog.cpp:(.text+0x30): first defined here
moc_FindDialog.o: In function `FindDialog::enableFindButton(QString const&)':
moc_FindDialog.cpp:(.text+0x50): multiple definition of `FindDialog::enableFindButton(QString const&)'
FindDialog.o:FindDialog.cpp:(.text+0x0): first defined here
collect2: ld returned 1 exit status
make: *** [findDialog] Error 1

我已经搜索了几个小时的问题,但我无法理解问题的根源。 什么会导致多重定义错误?

I wrote a findDialog which finds the text searched. When I give make command,it returns

g++ -Wl,-O1 -o findDialog FindDialog.o main.o moc_FindDialog.o    -L/usr/lib -lQtGui -lQtCore -lpthread 
moc_FindDialog.o: In function `FindDialog::findClicked()':
moc_FindDialog.cpp:(.text+0x20): multiple definition of `FindDialog::findClicked()'
FindDialog.o:FindDialog.cpp:(.text+0x30): first defined here
moc_FindDialog.o: In function `FindDialog::enableFindButton(QString const&)':
moc_FindDialog.cpp:(.text+0x50): multiple definition of `FindDialog::enableFindButton(QString const&)'
FindDialog.o:FindDialog.cpp:(.text+0x0): first defined here
collect2: ld returned 1 exit status
make: *** [findDialog] Error 1

I have searched the problem for hours, but I can not understand what the problem stems from.
What can cause multiple definition of error?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

情深已缘浅 2024-11-16 09:27:35

当方法定义包含在多个翻译单元(也称为目标文件)中时,通常会发生这种情况。后来,当链接器组合这些目标文件时,它发现同一方法有多个定义,并抱怨因为它不知道使用哪一个。下面是如何引入此错误的一个简单示例:

拥有包含方法声明及其定义的头文件 header.hpp

class foo {
public:
  void bar ();
};

void foo::bar ()
{
}

并拥有两个源文件 source1.cpp 和 source2.cpp 都包含该文件:

source1.cpp

#include "header1.hpp"
int example1()
{
  foo f;
  f.bar ();
}

...和source2.cpp

#include "header1.hpp"
int main ()
{
  foo f;
  f.bar ();
  f.bar ();
}

然后,分别编译两个文件并将它们链接在一起。例如:

g++ -c source1.cpp source1.o
g++ -c source2.cpp source2.o
g++ -o a.out source1.o source2.o

这会给你一个你在问题中描述的链接器错误,因为方法 foo::bar 在 source1 和 source2 对象中出现两次。链接器不知道该使用哪一个。

此问题有两种常见的解决方案:

解决方案 #1 - 内联该方法。

通过使用 inline 关键字声明该方法,编译器将内联整个方法,或者,如果决定不这样做,它将生成匿名方法(相同的方法,但对于给定的目标文件具有一些唯一的名称),所以目标文件中不会有冲突。例如:

class foo {
public:
  void bar ();
};

inline void foo::bar ()
{
}

解决方案#2 - 在另一个源文件中定义(实现)该方法,以便它在整个程序中仅出现一次。例如:

header1.hpp:

class foo {
public:
  void bar ();
};

header1.cpp

#include "header1.hpp"
void foo::bar ()
{
}

要决定是否内联,您必须知道(或至少猜测)调用此函数是否是比在整个程序中复制/内联此代码更昂贵。内联代码通常会使您的程序变得更大并增加编译时间。但这并不一定会使速度更快。另外,在源文件中有定义不会导致使用该函数重新编译所有源文件,而只会重新编译有定义的源文件,然后重新链接。许多程序员对 C++ 内联感到疯狂,但没有真正理解它如何影响程序。我建议仅在调用该函数成为性能瓶颈时才使用源文件中的定义并将其内联,否则将其内联将修复它。

希望有帮助。快乐编码!

It usually happens when method definition is included in multiple translation units, also called as object files. Later, when linker is combining those object files, it finds out that there are multiple definitions of the same method, and complains because it doesn't know which one to use. Here is a simple example of how to introduce this error:

Have header file header.hpp with both method declaration and its definition:

class foo {
public:
  void bar ();
};

void foo::bar ()
{
}

And have two source files source1.cpp and source2.cpp both including that file:

source1.cpp:

#include "header1.hpp"
int example1()
{
  foo f;
  f.bar ();
}

... and source2.cpp:

#include "header1.hpp"
int main ()
{
  foo f;
  f.bar ();
  f.bar ();
}

Then, compile two files separately and link them together. For example:

g++ -c source1.cpp source1.o
g++ -c source2.cpp source2.o
g++ -o a.out source1.o source2.o

That will give you a linker error you have described in your question, because method foo::bar appears twice, in both source1 and source2 objects. Linker doesn't know which one to use.

There are two common solutions to this problem:

Solution #1 - Have that method inlined.

By declared that method with inline keyword, compiler will either inline the whole method or, if it decides not to, it will generate anonymous method (same method but with some unique name for a given object file), so there will be no conflicts in object files. For example:

class foo {
public:
  void bar ();
};

inline void foo::bar ()
{
}

Solution #2 - Have definition (implementation) of that method in another source file, so that it appears only once in the whole program. For example:

header1.hpp:

class foo {
public:
  void bar ();
};

header1.cpp:

#include "header1.hpp"
void foo::bar ()
{
}

To decide whether to inline or not, you have to know (or at least make a guess) whether calling this function is more expensive than having this code duplicated / inlined all over the program. Inlined code usually makes your program bigger and increases compilation time. But it doesn't necessarily make it faster. Plus, having definition in source file will not result in re-compilation of all source files using that function, but only re-compilation of the source file that has definition, and then re-linking. Many programmers are going crazy about C++ inlining without really understanding how it affects the program. I'd recommend going with the definition in a source file and making it inline only if calling that function becomes a performance bottleneck and otherwise having it inlined will fix it.

Hope it helps. Happy coding!

原野 2024-11-16 09:27:35

在头文件中编写函数定义,然后在项目中的多个 .cpp#include这些头文件。与普遍的误解相反,头部防护装置不能保护您免受这种情况的影响。

仅在标头中写入以下内容:

  • 类定义
    • 可能包含成员函数的内联定义
  • 非成员变量声明
  • 非成员函数声明
  • 模板/内联函数定义

将其他所有内容都放在“源文件”中。

Writing function definitions in header files, and then #includeing these header files in multiple .cpps in your project. Contrary to popular misconception, header guards do not protect you from this.

Write only the following in headers:

  • Class definitions
    • May include inline definitions for member functions
  • Non-member variable declarations
  • Non-member function declarations
  • Template/inline function definitions

Put everything else in "source files".

吃颗糖壮壮胆 2024-11-16 09:27:35

从错误消息中的文件名来看,您有一些模拟测试装置作为 TDD 的一部分和一些真实的代码。链接器确实相当清楚地报告了问题所在 - 为了更加清晰,我通过删除部分信息重新格式化了此处的信息:

moc_FindDialog.cpp: multiple definition of `FindDialog::findClicked()'
FindDialog.cpp:     first defined here

moc_FindDialog.cpp: multiple definition of `FindDialog::enableFindButton(QString const&)'
FindDialog.cpp:     first defined here

这清楚地表明链接器首先遇到了 moc_FindDialog.cpp,然后在 FindDialog.cpp 中遇到第二个定义。

我认为您需要仔细查看 moc_FindDialog.cpp 中的模拟测试装置并确定为什么要复制这两个函数。或者,也许您不应该在单个程序中链接模拟函数和实际函数 - 这两个源文件根本不打算链接到单个程序中。

Judging from file names in the error messages, you have some mock test fixtures as part of TDD and some real code. The linker did report where the trouble is fairly clearly - I've reformatted the information here for extra clarity by removing part of the information:

moc_FindDialog.cpp: multiple definition of `FindDialog::findClicked()'
FindDialog.cpp:     first defined here

moc_FindDialog.cpp: multiple definition of `FindDialog::enableFindButton(QString const&)'
FindDialog.cpp:     first defined here

This clearly states that the linker first encountered each of the function definitions in moc_FindDialog.cpp, and then encountered the second definition in FindDialog.cpp.

I think you need to look hard at the mock test fixture in moc_FindDialog.cpp and determine why those two functions are replicated. Or, maybe you are not supposed to link both the mock functions and the real functions in a single program - the two source files are simply not intended to be linked into a single program.

合久必婚 2024-11-16 09:27:35

弗拉德·拉扎连科的回答很好。

我只是补充一下我在使用QT/C++时遇到的另一种可能性:

当你声明一个槽时,你不需要写定义(实现),否则,你会得到一个错误:多重定义

Vlad Lazarenko's answer is good.

I just add another possibility that I met when using QT/C++:

When you declare a slot, you don't need to write a definition (implementation), otherwise, you will get an error: multiple definition

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文