81

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

24 回答 24

81

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

于 2013-01-05T14:35:12.107 回答
66

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

于 2013-04-09T22:10:58.500 回答
37

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

这个答案基于 Qt Creator。

不像名字所暗示的那样,Rebuild Project不会消灭一切并从头开始构建。如果您最近将QObject(和/或 Q_OBJECT)添加到您的班级,您将不得不qmake再次运行,例如

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

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

作为后备,为了暴力 Qt 从头开始​​构建所有内容,请删除DebugorRelease文件夹。

于 2013-07-03T06:22:01.993 回答
12

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

于 2013-03-27T00:36:45.033 回答
8

我手动将 cpp/ui 文件添加到我的项目中,但忘记将头文件显式添加为头文件。现在,在编译时,我收到了与上面类似的错误消息,并且 moc_*.cpp 文件未在构建的调试(或发布)目录中生成。这不是一个明显的错误,qmake 没有抱怨,除了链接器消息之外我没有收到任何错误。

因此,如果有人再次遇到同样的问题(或犯同样的复制和粘贴错误):确保头文件也已添加到您的项目文件中

于 2016-07-12T09:09:44.807 回答
7

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

于 2014-12-25T12:07:42.880 回答
6

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

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

然后在自定义构建工具配置中:

  1. 转到一般
  2. 将“命令行”设置为:

    "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(文件名).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_DEBUG "-I-I-DEFINES_DEFINED" .\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 插件应用。

于 2016-08-31T02:39:55.110 回答
5

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

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

于 2016-05-18T09:18:15.027 回答
4

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

于 2013-10-28T03:16:04.533 回答
3

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

所以我使用这个答案中的解决方案将文件添加到麦克风列表中:

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

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

之后,构建您的项目。

在-ModeDebug中构建一次Release

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

现在,“moc_filename.cpp”应该在Generated Files\Debugand中Generated Files\Release

右键单击它们中的每一个并更改它们的属性:

  • 中的文件Debug: 将配置更改为Release,然后更改General->Excluded from buildyes.
  • 中的文件Release: 将配置更改为Debug,然后更改General->Excluded from buildyes.
于 2018-11-30T02:32:23.677 回答
2

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

于 2020-11-17T18:56:34.207 回答
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 行为。

于 2013-07-10T09:31:06.267 回答
1

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

于 2014-01-22T08:22:07.607 回答
1

在使用“ PIMPL ”(私有实现)编程模式时,我在 Qt 中使用“私有类”时遇到了这个问题。Qt 在整个源代码中都使用了这个模型。我自己已经非常喜欢它了。

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

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

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

我强烈建议您学习 PIMPL 模式——尤其是如果您要阅读内部 Qt 源代码。

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

#include "MyPublicClass.moc"

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

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

  1. “正常”包括已定义。
  2. 定义了私有类。
  3. 公共类的 moc 是#included。
  4. 定义了公共类实现。
于 2014-03-06T22:37:34.240 回答
1

视觉工作室 2017。

我已将文件添加到已设置 Qt 项目并收到此错误。我如何修复它:

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

瞧:)

于 2020-02-06T08:48:37.827 回答
0

我最近从 MingW 切换到 MSVC 时发生了这种情况。我有一个原型类/结构列为类,MingW 不介意。

MSVC 肯定看到了原型设计之间class的差异。struct

希望有一天能帮助别人。

于 2014-10-03T20:27:38.530 回答
0

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

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

于 2015-02-19T16:35:05.670 回答
0

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

#ifndef MYCLASSNAME_H
#define MYCLASSNAME_H

... // all the header file content.

#endif
于 2016-01-11T14:36:17.350 回答
0

在 VS 2013 环境中,任何一个答案都适用于我。我最终通过从项目中删除.h/ .cpp 并将其添加回来 解决了这个问题。

于 2016-08-12T19:02:51.290 回答
0

我正在使用集成的 Perforce p4v 客户端在 VS2015 中工作。就我而言,Perforce 尝试将 moc 文件添加到 depo,当我恢复此操作时,Perforce 从项目中删除了这个 moc 文件并将其删除。该文件在下一次编译后重新创建,但它没有包含在项目中,我必须手动将其添加到生成的文件中,当我终于明白问题出在哪里时。

于 2017-07-09T17:59:43.790 回答
0

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

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

于 2018-06-29T17:28:09.683 回答
0

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

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

#include "MyClass.h""

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

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

于 2018-07-23T12:30:48.153 回答
0

对我来说,这就是原因:QT的项目文件中没有包含一些头文件或源文件

于 2018-09-13T01:38:37.660 回答
0

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

于 2020-12-11T14:48:09.113 回答