未解析的外部符号“ public:虚拟结构QMetaObject const * __thiscall父对象


74

我从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)

Answers:


77

您应该删除debug应用程序的文件夹,然后再次运行以更正此问题。


7
我有同样的问题。删除调试文件夹没有帮助。还有其他想法吗?
维尔恩·詹森2013年

2
@Vern Jensen,检查Q_OBJECT宏,然后重建,然后删除debug / release文件夹(以删除所有moc文件)并再次重建。其中之一应该有所帮助。
SpongeBobFan

19
从类中删除Q_OBJECT宏,保存并添加Q_OBJECT再次对我有用,当使用VS 2012的QT5插件时
Beachwalker

这也解决了我的问题。但是为什么以及如何?有人请解释。谢谢!
Nayan Soni'2

5
我在上课时遇到同样的问题。我发现完全删除Q_OBJECT宏解决了我的问题。不知道为什么。但是,如果我放回原处,则会收到相同的3个未解决的错误。我通过在.proQTcmakelists.txt文件和我正在使用的文件中包含新类来解决该问题。一旦我包含了头文件和cpp文件,代码就可以使用了QObject
卡亚特

64

如果您使用的是Visual Studio,请Q_OBJECT从头文件中删除该行,保存该文件,放Q_OBJECT回头文件中,然后再次保存该文件。这应该生成moc_*文件,并且应该正确构建和链接。


3
没有其他解决方案对我有用,但是确实可以!谢谢!;)
zeFree 2014年

4
如果您使用的是CMake,请确保您拥有set(CMAKE_AUTOMOC ON)
Matt

2
此答案也应记为有效答案!
Adiel Yaacov

2
谢谢我(VS2017),谢谢。注释掉“ Q_OBJECT”的编译,如果恢复则不编译。不会激发人们对Qt的信心。我认为“ Q_OBJECT”宏是必要的吗?
Pierre

我也使用VS2017。发生以下情况:我将AUTOMOC添加到了CMakeLists。这使我的编译器cho之以public signal:鼻。不过,无论何时Q_OBJECT在代码中,我都有链接器错误,并且运行时错误说我的自定义类未定义类型。
吓了一跳

34

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

该答案基于Qt Creator。

与顾名思义的不同,它Rebuild Project不会清除所有内容并从头开始构建。如果您最近向类中添加了QObject(和/或Q_OBJECT),则必须qmake再次运行,例如

  1. 清洁项目
  2. 运行qmake
  3. 建立项目

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

作为回退,使用蛮力Qt从头开始构建所有内容,请删除DebugRelease文件夹。


1
辉煌!为我工作。“运行qmake”是关键步骤。如果要使用插槽,则需要Q_OBJECT。
Pierre

11

所以问题是我需要Qt MOC编译器来编译我的.h文件。这是扩展QObject或其子级之一的任何类所必需的。对该修复程序涉及(对我而言),右键单击头文件,选择“属性”,然后将“项目类型”设置为“ Qt MOC输入”,然后在头文件上单击“编译”,然后将生成的moc_myfilename.cpp文件添加到我的项目。


您究竟在哪里找到此“属性”?在Qt Creator中,右键单击后看不到任何类似的信息。
Horst Walter

1
这在XCode中,右键单击“导航器”视图中列出的文件(您的项目使用的文件列表)。
维尔恩·詹森

1
在Visual Studio中也可以做到这一点,但是其他人将不得不告诉您确切的配置方法。(我相信您可以在Qt的网站上找到答案。)
Vern Jensen

1
对于傻笑,我添加了一个头文件和一个.cpp文件,并将QtObject派生类移入其中,然后还必须在头文件中#include <QtObject>,然后突然起作用。这些东西应该被记录的地方....
BitTickler

1
为我工作,除了类型是“自定义构建工具”而不是“ Qt MOC输入”。我使用Visual Studio 2017
队长普通

7

如果您的Moc文件是在Visual Studio项目中生成的,则尝试将它们包含在项目中(如果未包含在项目中),然后重新生成。


为什么那是必要的?
lpapp 2014年

由于VS的某些错误配置,导致无法使用moc文件。有时,即使正确生成MOC文件,但因为他们是不包括在内,它表现得像它不存在
类似于耶尔马兹

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 -DWIN-E_STAT_E_STAT_E_FIN_E _-_ I ___ I_E _-_ I_E _-_ I_FI_E_-I_FI_D_E_-I_FI_D_E 。\ GeneratedFiles“” -I。“ “ -I $(QTDIR)\ include” -I。\ GeneratedFiles \ $(ConfigurationName)。“ -I $(QTDIR)\ include \ QtCore”“ -I $(QTDIR)\ include \ QtGui”“ -I $(QTDIR)\ include \ QtNetwork”

  3. 将“输出”设置为:

    。\ GeneratedFiles \ $(配置名称)\ moc _%(文件名称).cpp

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


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


为我工作,除了我可以在第一组1,2,3步骤之后停下来;自定义构建工具配置可能已在某处定义。我使用Visual Studio 2017
队长普通

4

我使用CMake来管理Qt项目,并且需要在QT4_WRAP_CPP调用下添加新的Q_OBJECT。这将生成moc _ *。cxx包含在项目中,并清理未解决的外部环境。


4

当我的cpp文件中有Q_OBJECT类定义时,我在Visual Studio 2012中遇到了此问题。将类定义移至头文件可解决此问题。

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


1
这也是我的问题。恼人的是不得不在头文件中公开内部类。
Zitrax

3

我将cpp / ui文件手动添加到了项目中,但是忘记了将头文件明确地添加为头文件。现在,当进行编译时,我得到了与上述类似的错误消息,并且在生成的debug(或发布)目录中未生成moc _ *。cpp文件。那不是一个明显的错误,qmake没有抱怨,除了链接器消息我没有任何错误。

因此,如果有人再次遇到相同的问题(或犯下相同的复制和重复错误):请确保将头文件也添加到了项目文件中


3

我的问题是我的一个使用Qt宏的文件没有被锁住。我发现,Visual Studio的Qt插件无法识别Q_NAMESPACE宏,因此不会将文件添加到移动列表中。

因此,我使用此答案中的解决方案将文件添加到麦克风列表中:

您应该找到一个已成功生成“ moc_ *”的.h文件,并将“自定义构建工具->常规”中的所有内容复制到新的.h文件设置页面。

请注意DebugRelease-Mode的不同选项。

之后,构建您的项目。

DebugRelease模式下分别构建一次

最后,将生成的“ moc_ *”文件添加到您的项目中。

现在,“ moc_filename.cpp”应该位于Generated Files\Debug和中Generated Files\Release

右键单击它们中的每个,然后更改其属性:

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

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

1

就我而言(将QtAdd-in与VS2012和Qt v4.8.4一起使用),上述建议均无效。由于某种原因,VS无法生成正确的moc文件(生成输出:未找到相关类。未生成输出。),当我手动编译相关头文件(将qt moc设置为编译器并单击“编译”)时,它生成了空的moc文件。

起作用的是从命令行(moc -o moc_SomeClass.cpp SomeClass.h)编译所有必需的mocs,然后在GeneratedFiles文件夹中替换错误的Mocs。

这是成功完成项目的唯一解决方法(对于大型项目而言,这不是一种方便的解决方法),但是并不能真正解释奇怪的VS / QtAdd-in行为。


1

通过将QtAdd-in与VS2010结合使用,我意识到moc _ *。cpp文件已在GeneratedFiles / Debug文件夹中更新,尽管我处于发布模式。将文件复制到Release文件夹对我有用。


1

在采用“ PIMPL ”(私有实现)编程模式时,我在Qt中使用“私有类”遇到了这个问题。Qt整个源代码都使用此模型。我本人真的很喜欢它。

此技术涉及在公共头文件中使用“私有”前向声明的类,该类将由“公共”类(即它的“父”)使用。然后,父级有一个指向私有类实例的指针作为数据成员。

“私有”类完全在cpp文件中为公共类定义。私有类没有头文件。

所有“肮脏的工作”都是通过该私有类完成的。这将隐藏您的公共类的所有实现,通常包括其他所有私有成员(数据和函数)。

我强烈建议您学习PIMPL模式-特别是如果您要阅读内部Qt源代码的话。

无需进一步解释该编码风格,这是与这个问题有关的要点...若要使Q_OBJECT宏在cpp中起作用,以使“私有”类成为可以使用信号/插槽等的QObject,您需要明确将.moc包含在cpp中的公共类中

#include "MyPublicClass.moc"

您可以忽略有关此行的所有IDE警告。

我不确定这是否真的很重要,但是我总是会在私有类定义之后看到包含,而不是放在cpp的顶部(就像通常放置include一样)。因此,cpp布局如下所示:

  1. 定义了“普通”包括。
  2. 定义了私有类。
  3. 公共类的Moc已包含#include。
  4. 定义了公共类的实现。

1

Visual Studio 2017。

我已将文件添加到已设置的Qt项目中,并收到此错误。我如何解决它:

右键单击解决方案资源管理器属性中的标题 ...- >配置属性->常规->项类型C / C ++标题更改为Qt元对象编译器(moc)

瞧:)


0

从MingW切换到MSVC时,这最近发生在我身上。我有一个原型类/结构列为类,而MingW不在乎。

MSVC肯定会在原型开发classstruct原型开发之间有所区别。

希望有一天能对别人有帮助。


0

就我而言,以上方法均无效,但这完全是我的错误。

我已经在.h文件中覆盖了虚函数(声明了它们),但是从未在.cpp中定义它们:)


0

我通过将其添加到头文件中解决了我的问题:

#ifndef MYCLASSNAME_H
#define MYCLASSNAME_H

... // all the header file content.

#endif

0

在VS 2013环境中,这两个答案都对我有效。我最终通过从项目中删除.h / .cpp并将其重新添加来解决该问题。


0

我正在使用集成的Perforce p4v客户端在VS2015中工作。在我的案例中,Perforce尝试将moc文件添加到仓库中,当我还原此操作时,Perforce从项目中删除了该moc文件并删除了它。在下次编译后重新创建了该文件,但该文件未包含在项目中,当我最终了解问题出在哪里时,我必须将其手动添加到“生成的文件”中。


0

我有同样的问题,我的解决方案是编码(我的文件“ UTF16LE BOM”无法使用moc.exe生成),使用ASCII编码创建另一个文件,它可以工作。

HxD HexEditor可以帮助您查看编码。


0

我知道这是一个非常老的问题,但是它似乎仍然很有趣(在过去的几个月中,我至少来过4到5次),而且似乎我发现了可能导致此错误的另一个原因。

在我的头文件中,我输入错误:

#include "MyClass.h""

仅在检查了整个输出之后,我才发现在那一行编译器正在发出警告。

现在,我删除了附加引号,我的QObject可以完美编译!


0

对我而言,这是原因:QT的项目文件中未包含某些标头或源文件


0

在链接的CMake目标的情况下面临此问题。CMAKE_AUTOMOC事实证明,即使在不直接(传递)使用Qt的目标中,我也必须启用。事实证明,CMAKE_AUTOMOC不能find_package(QtX)在同一个CMakeLists.txtCMakeLists.txt父级中使用。


0

就我而言,我在项目的子文件夹中有问题的QObject祖先的.h和.cpp文件。当我将它们移到CMakeLists.txt(项目根文件夹)旁边时,它已成功链接。我可能缺少一些CMake命令,以将mocs fot文件包含在子目录中。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.