奇怪的"多重定义"错误

时间:2014-05-27 02:47:08

标签: c++ qt pointers

我在Qt / MinGW / Windows的大项目中工作。最近我改变了一些源文件的位置并重新编译它们,经过一些修正后,我开始接收消息,如

(.idata$5+0x0):-1: error: multiple definition of `_imp___ZN9QwtThermo16staticMetaObjectE'

这有两个类:QwtThermo和QwtPlotPicker在一个代码中,之前没有这样的错误(记住:我只是将基本文件夹中的文件位置更改为一些子文件夹;没有代码更改(据我记得) )并注意到许多其他Qwt类也包含在内并且通常在没有任何编译错误的情况下使用;这是唯一两个给我带来问题的类。)

现在""的多重定义是C ++中的一个常见错误,我已经知道通常如何解决它(许多线程,包括在StackOverflow中,谈论它):只应在头文件中声明事物,同时在.cpp文件中定义它们。

不幸的是,这次似乎并不是一个可行的解决方案。这是正在发生的事情:

  • 我做了一个关于这个标题包含在哪里的研究,我没有发现任何问题。我很难过,以前用它很好地编译。
  • 问题只会出现在QwtPlotPicker中,如果我创建它的子类(如果我使用它并不重要)。如果我只在头文件中声明子类的名称并在.cpp中定义它,那么我就可以编译了,但是一旦我开始使用它(在头文件中声明了成员指针),那么编译错误"未定义的参考' vtable for Picker'"出现。因此,在标题中声明类并在.cpp中定义它实际上并没有帮助;
  • 使用QwtThermo,如果我在头文件中包含文件并且只声明指向它的指针(没有子类),则错误开始出现。如果我只在我的项目头中声明QwtThermo类并在.cpp文件中包含QwtThermo自己的头,这就解决了。通过这种方式,我能够声明一个指向它的成员指针,并使用" new"来实例化指针。在它的父类中的.cpp文件中,但是一旦我通过调用它的方法开始使用它,"""的多重定义开始再次出现。

你可能会看到,这次似乎不仅仅是在标题中声明并在.cpp"中定义它。更多的事情正在发生。 :T

那可能是什么错?对不起,不发布任何代码,但请相信我已经可以看到的所有有趣的内容;发布代码的唯一变化是复制超过5000行^^

我很高兴你能给我任何帮助:)。

谢谢,


编辑 :以下是来自Qt Creator"编译输出"的代码:

g++ -c -pipe -fno-keep-inline-dllexport -g -frtti -Wall -Wextra -fexceptions -mthreads -DUNICODE -DMGENERALDEFINES_GUI -DMGENERALDEFINES_DEBUG -DMGENERALDEFINES_GENERAL -DQWT_INCLUDED -DDEBUG -DRELEASE -DQT_NO_DEBUG -DQT_NO_DEBUG_OUTPUT -DQT_PRINTSUPPORT_LIB -DQT_MULTIMEDIA_LIB -DQT_WIDGETS_LIB -DQT_SQL_LIB -DQT_NETWORK_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_NEEDS_QMAIN -I. -I"MSHARE_REPO" -I"MSHARE_COMMON" -I"C:\Qt\Qwt-6.1.0\include" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include\QtPrintSupport" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include\QtMultimedia" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include\QtWidgets" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include\QtSql" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include\QtNetwork" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include\QtGui" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\include\QtCore" -I"build\moc" -I"build\ui" -I"C:\Qt\Qt5.2.1\5.2.1\mingw48_32\mkspecs\win32-g++" -o build\obj\moc_mainwindow.o build\moc\moc_mainwindow.cpp
g++ -Wl,-subsystem,windows -mthreads -o debug\mShare.exe object_script.mShare.Debug  -lglu32 -lopengl32 -lgdi32 -luser32 -lmingw32 -lqtmaind "D:/Minhas obras/Softwares/mShare Project/mShare/SMTPEmail.dll" -lpsapi C:/Qt/Qwt-6.1.0/lib/qwtd.dll "D:/Minhas obras/Softwares/mShare Project/mShare/../../Classes/mLogger/build/debug/mLogger.dll" "D:/Minhas obras/Softwares/mShare Project/mShare/../mShareLib/build/debug/mShareLib.dll" C:/Qt/Qwt-6.1.0/lib/qwt.dll "D:/Minhas obras/Softwares/mShare Project/mShare/../../Classes/mLogger/build/release/mLogger.dll" "D:/Minhas obras/Softwares/mShare Project/mShare/../mShareLib/build/release/mShareLib.dll" -LC:\Qt\Qt5.2.1\5.2.1\mingw48_32\lib -lQt5PrintSupportd -lQt5Multimediad -lQt5Widgetsd -lQt5Sqld -lQt5Networkd -lQt5Guid -lQt5Cored .\build\obj\icone_res.o 
d000171.o:(.idata$5+0x0): multiple definition of `_imp___ZN13QwtPlotPicker16staticMetaObjectE'
d000022.o:(.idata$5+0x0): first defined here
d000171.o:(.idata$6+0x0): multiple definition of `_nm___ZN13QwtPlotPicker16staticMetaObjectE'
d000022.o:(.idata$6+0x0): first defined here
d000172.o:(.idata$5+0x0): multiple definition of `_imp___ZN9QwtThermo16staticMetaObjectE'
d000102.o:(.idata$5+0x0): first defined here
d000172.o:(.idata$6+0x0): multiple definition of `_nm___ZN9QwtThermo16staticMetaObjectE'
Makefile.Debug:246: recipe for target 'debug\mShare.exe' failed
d000102.o:(.idata$6+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
mingw32-make[1]: [debug\mShare.exe] Error 1 (ignored)

3 个答案:

答案 0 :(得分:1)

我可能错了,因为我不知道你的代码是什么样子,但听起来好像是多次编译这些类?如果您还没有将#pragma一次添加到头文件的顶部,以确保只有该类的一个编译副本。希望你能尽快找到解决方案!

答案 1 :(得分:1)

有些事情可能会引起人们的兴趣。我注意到你的错误谈到了static keyword。您的代码可能声明静态变量并在许多地方初始化它。

另一个原因可能是您没有使用ifndefpragma once来确保只为所有类+标头初始化一个实例。 你需要在标题中加上这样的东西:

#ifndef MY_HEADER_H
#define MY_HEADER_H

... // all of your code

#endif

答案 2 :(得分:0)

好吧,经过一些尝试和重试后,我设法找到了问题所在的地方 - 但不知道如何解决问题。问题的存在是因为在我的Qt .pro文件中,我尝试为调试编译配置一些特定配置,而其他配置用于发布编译,但由于某种原因,系统没有区分这两种配置。更具体地说,以下代码应该有效:

win32 {
    LIBS += -lpsapi

    debug {
        LIBS += C:/Qt/Qwt-6.1.0/lib/qwtd.dll \
            $${MLOGGER}/build/debug/mLogger.dll \      
            $${MSHARE_LIB}/build/debug/mShareLib.dll  
        DEFINES += DEBUG
    }

    release {
        LIBS += C:/Qt/Qwt-6.1.0/lib/qwt.dll \
            $${MLOGGER}/build/release/mLogger.dll \
            $${MSHARE_LIB}/build/release/mShareLib.dll
        DEFINES += RELEASE \
           QT_NO_DEBUG \
           QT_NO_DEBUG_OUTPUT
    }
} # win32

因为在关于qmake的Qt助手文件中,这是使用辅助范围编写此类配置的方法:

win32 {
    debug {
        CONFIG += console
    }
}

我注意到,在评论"发布"部分,问题消失了,我能够毫无错误地编译;如果评论被删除,问题就会恢复。同时,虽然没有注释,但我能够注意到版本定义已定义,尽管事实上我处于调试编译状态'。最后,这是一个在我的更改之前不存在的代码。

唯一的问题是:为什么qmake无法正确解释.pro文件?但是我会把它放在另一个问题上。

感谢您的帮助,