未解决的外部符号 "public: virtual struct QMetaObject const * __thiscall Parent

88

我从 QObject 类继承:

class Parent: public QObject
{
    Q_OBJECT
    QObject* cl;

public:
    Parent(QObject *parent=0):QObject(parent) {
        cl = NULL;
    }

    QObject* getCl() const {
        return cl;
    }
    void setCl(QObject *obj) {
        cl = obj;
    }
};

但是当我写:

Parent ev;

我遇到了如下错误:
main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __thiscall Parent::metaObject(void)const " (?metaObject@Parent@@UBEPBUQMetaObject@@XZ)

main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual void * __thiscall Parent::qt_metacast(char const *)" (?qt_metacast@Parent@@UAEPAXPBD@Z)

main.obj:-1: error: LNK2001: unresolved external symbol "public: virtual int __thiscall Parent::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@Parent@@UAEHW4Call@QMetaObject@@HPAPAX@Z)

编辑.vcxproj文件对我有效...检查所有的.h或.hh文件是否在QtMoc标签中:<QtMoc Include="main_app.h" />;其他事情我已经检查过了。 - lRadha
27个回答

84
您需要删除应用程序中的 debug 文件夹,然后再次运行以解决此问题。

10
我跟你遇到了相同的问题,删除调试文件夹没有起作用。还有其他的想法吗? - Vern Jensen
2
@Vern Jensen,请检查是否有 Q_OBJECT 宏,然后重新构建,接着删除 debug/release 文件夹(以删除所有 moc 文件),最后再次进行构建。其中一个步骤应该会有所帮助。 - SpongeBobFan
21
在使用QT5插件的VS 2012时,从类中移除Q_OBJECT宏,保存后再添加Q_OBJECT宏对我很有效。 - Beachwalker
7
我在完成一项课程项目时遇到了相同的问题。我发现直接删除Q_OBJECT宏可以解决问题,但不知道原因。但是如果我重新加入这个宏,就会出现相同的三个未解决错误。我通过在QT的.pro文件和我正在使用的cmakelists.txt文件中包含新类来解决这个问题。一旦我包括了头文件和cpp文件,代码就可以使用QObject - Callat
1
我在Visual Studio上的一个CMake项目中遇到了同样的问题。像@Callat一样,删除Q_OBJECT宏可以解决问题,但这并不好。后来发现我忘记将头文件添加到cmakelists.txt中,所以我认为MOC没有对其进行处理。只需将头文件添加到cmakelist中即可。 - qwark
显示剩余2条评论

69

如果你正在使用Visual Studio,从头文件中删除Q_OBJECT这一行,保存文件,再将Q_OBJECT放回头文件中,再次保存文件。这样应该会生成moc_*文件,并且可以正确构建和链接。


3
除了这个方法,其他方法都对我没用!谢谢! ;) - zeFree
6
如果您正在使用CMake,请确保您已经设置了set(CMAKE_AUTOMOC ON) - Matt
2
此答案也应被记录为有效答案! - Adiel Yaacov
3
对我有用(VS2017),谢谢。如果将“Q_OBJECT”注释掉,可以编译,但恢复后无法编译。这不会激发对Qt的信心。我原以为“Q_OBJECT”宏是必需的? - Pierre
我也在使用VS 2017。以下是我的情况:我在我的CMakeLists中添加了AUTOMOC。这使得我的编译器无法处理之前可以处理的public signal:。但是,每当代码中有Q_OBJECT时,我仍然会遇到链接器错误,并且会出现运行时错误,提示我的自定义类未定义类型。 - starturtle

37

我注意到有些答案是基于Visual Studio的。

这个答案是基于Qt Creator的。

与名称所示不同,Rebuild Project 不会抹掉所有内容并从头开始构建。如果您最近向类中添加了 QObject (和/或 Q_OBJECT),则必须再次运行 qmake,例如:

  1. 清理项目
  2. 运行 qmake
  3. 构建项目

这是因为,默认情况下,qmake 仅在您对解决方案进行重大更改时才运行,例如添加新源文件或修改 .pro 文件。如果您编辑现有文件,则它不知道需要运行 qmake

作为后备,为了强制Qt从头开始构建所有内容,请删除 DebugRelease 文件夹。


1
太棒了!对我有用。"运行qmake"是关键步骤。如果你要使用slots,Q_OBJECT是必需的。 - Pierre

13

问题在于我需要Qt MOC编译器来编译我的.h文件。对于任何扩展QObject或其子类之一的类,都需要此编译器。修复方法(对于我而言)是右键单击头文件,选择“属性”,将项目类型设置为“Qt MOC输入”,然后点击头文件上的“编译”,最后将生成的moc_myfilename.cpp文件添加到我的项目中。


1
这是在XCode中,右键单击“导航器”视图中列出的文件(您的项目使用的文件列表)。 - Vern Jensen
1
这在Visual Studio中也是可能的,但是其他人必须告诉您如何在那里配置它。(我相信您可以在Qt的网站上找到答案。) - Vern Jensen
1
为了好玩,我添加了一个头文件和一个.cpp文件,并将我的QtObject派生类移动到其中,然后还必须在头文件中#include <QtObject>,突然它就起作用了。这些东西真的应该在某个地方有文档记录... - BitTickler
3
对我起作用,除了类型是"自定义构建工具"而不是"Qt MOC输入"之外。我使用的是Visual Studio 2017。 - Captain Normal
2
在VS 2019中,它被称为“Qt元对象编译器(moc)”,当我更改它时,它对我有用。 - danieltakeshi
显示剩余6条评论

9
我手动将cpp/ui文件添加到我的项目中,但是忘记明确地添加头文件作为头文件。现在编译时出现了类似上面的错误消息,并且moc_*.cpp文件没有生成在构建的调试(或发布)目录中。这不是一个很明显的错误,qmake没有抱怨,除了链接器消息之外,我没有收到任何错误信息。
因此,如果有人再次遇到同样的问题(或者犯了同样的复制和粘贴错误):确保头文件也已经被添加到你的项目文件中

8

如果您的 moc 文件是在 Visual Studio 项目中生成的,请尝试将它们包含到项目中。如果它们没有被包含到项目中,请重新构建。


为什么会有这种必要性? - László Papp
由于VS的一些错误配置导致无法使用moc文件。有时即使它正确生成了moc文件,但由于它们没有被包含,它的行为就像它不存在一样。 - Akın Yılmaz

6

我在Visual Studio中遇到了同样的问题,通过以下步骤解决:

  1. 在解决方案资源管理器中右键单击头文件
  2. 属性
  3. 将“项类型”更改为“自定义生成工具”

然后在自定义生成工具配置中:

  1. 进入通用设置
  2. 将“命令行”设置为:

    "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fStdAfx.h" "-f../../../src/FileName.h" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_NETWORK_LIB -DWIN32_LEAN_AND_MEAN -DDIS_VERSION=7 -D_MATH_DEFINES_DEFINED "-I.\SFML_STATIC" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork"

  3. 将“输出”设置为:

    .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp

  4. 将“附加依赖项”设置为:
    $(QTDIR)\bin\moc.exe;%(FullPath)


您的确切值可能会有所不同。它们通常通过Qt插件应用。


对我来说很有效,除了我可以在第一组1,2,3步骤后停止;自定义构建工具配置可能已经在某个地方定义。我正在使用Visual Studio 2017。 - Captain Normal

5

当我在cpp文件中定义了Q_OBJECT类时,我在使用Visual Studio 2012时遇到了这个问题。将类定义移动到头文件中解决了此问题。

看起来应该可以通过将cpp文件添加到moc来支持cpp文件中的Q_OBJECT类,但我没有尝试过这种方法。


1
这也是我的问题。虽然在头文件中公开一个内部类很烦人。 - Zitrax

4

我使用CMake来管理Qt项目,而在QT4_WRAP_CPP调用下需要添加新的Q_OBJECT。这将生成moc_*.cxx文件以便在项目中包含,并清除未解决的外部引用。


3
我的问题是,我使用了Qt宏之一的文件没有被moc'ed。我发现,Visual Studio的Qt插件不识别Q_NAMESPACE宏,因此不会将文件添加到moc'ing列表中。
所以我使用this answer的解决方案将文件添加到mic'ing列表中:
引用: 您应该找到一个成功生成“moc_*”文件的.h文件,并将“Custom Build Tool -> General”中的所有内容复制到新的.h文件设置页面中。
小心Debug和Release模式的不同选项。
之后,构建您的项目。
在Debug和Release-Mode中分别构建一次。
最后,将生成的“moc_*”文件添加到您的项目中。
现在,“moc_filename.cpp”应该在Generated Files\Debug和Generated Files\Release中。

右键点击它们,更改它们的属性:

  • Debug文件:将配置更改为Release,然后将General->Excluded from build更改为yes
  • Release文件:将配置更改为Debug,然后将General->Excluded from build更改为yes

这是一个被低估的答案。 - Jacob Krieg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接