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

时间:2013-01-05 10:11:26

标签: c++ qt qobject

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

24 个答案:

答案 0 :(得分:64)

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

答案 1 :(得分:55)

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

答案 2 :(得分:29)

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

这个答案基于Qt Creator。

与名称建议不同,Rebuild Project不会消除所有内容并从头开始构建。如果您最近在课程中添加了QObject(和/或Q_OBJECT),则必须再次运行qmake,例如

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

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

答案 3 :(得分:8)

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

答案 4 :(得分:7)

如果您的moc文件是在visual studio项目中生成的,如果它们未包含在项目中,则尝试将它们包含到项目中,然后重建。

答案 5 :(得分:6)

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

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

    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 _%(文件名).cpp

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

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

答案 6 :(得分:4)

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

答案 7 :(得分:3)

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

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

答案 8 :(得分:2)

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

因此,如果有人再次遇到同样的问题(或者造成相同的副本和错误):确保标题文件也已添加到项目文件中

答案 9 :(得分:1)

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

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

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

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

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

没有进一步解释编码风格,这里是与这个问题相关的要点...要使Q_OBJECT宏在cpp内工作,“private”类为QObject,可以使用信号/插槽等,你需要明确地将.moc包含在cpp内的公共类中

#include "MyPublicClass.moc"

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

我不确定它是否真正起作用,但是我总是看到包含在私有类定义之后,而不是在cpp的顶部(如包括通常放置)。所以,cpp布局是这样的:

  1. “正常”包含已定义。
  2. 定义了私有类。
  3. 公共类的moc是#included。
  4. 定义了公共类实现。

答案 10 :(得分:1)

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

答案 11 :(得分:1)

在我的情况下(使用VS2012和Qt v4.8.4的QtAdd-in)上述建议都没有奏效。 由于某种原因,VS无法生成正确的moc文件(构建输出:没有找到相关的类。没有生成输出。)当我手动编译相关的头文件(将qt moc设置为编译器并单击“编译”)时,它生成了空的moc文件。

从命令行(moc -o moc_SomeClass.cpp SomeClass.h)编译所有必要的mocs然后在GeneratedFiles文件夹中替换错误的mocs是做了什么工作。

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

答案 12 :(得分:1)

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

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

  

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

请注意DebugRelease模式的不同选项。

  

然后,构建您的项目。

DebugRelease模式下分别构建一次

  

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

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

右键单击它们,然后更改其属性:

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

答案 13 :(得分:1)

Visual Studio 2017。

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

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

瞧:)

答案 14 :(得分:0)

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

当涉及原型设计时,MSVC肯定会看到classstruct之间的差异。

希望有一天能帮助别人。

答案 15 :(得分:0)

在我的情况下,以上都没有奏效,但这完全是我的错误。

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

答案 16 :(得分:0)

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

#ifndef MYCLASSNAME_H
#define MYCLASSNAME_H

... // all the header file content.

#endif

答案 17 :(得分:0)

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

答案 18 :(得分:0)

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

答案 19 :(得分:0)

我遇到了同样的问题,我的解决方案是编码(我的文件“ UTF16LE BOM”无法通过moc.exe生成),使用ASCII编码创建另一个文件即可。

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

答案 20 :(得分:0)

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

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

#include "MyClass.h""

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

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

答案 21 :(得分:0)

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

答案 22 :(得分:0)

在链接有CMake目标的情况下解决了此问题。原来,即使在不直接(传递)使用Qt的目标中,我也必须启用CMAKE_AUTOMOC。同样证明,CMAKE_AUTOMOC不能与父级的同一find_package(QtX)CMakeLists.txt中的CMakeLists.txt一起使用。

答案 23 :(得分:0)

在我的情况下,项目子文件夹中存在问题的QObject祖先的.h和.cpp文件。当我将它们移到CMakeLists.txt(项目根文件夹)旁边时,它已成功链接。我可能会丢失一些CMake命令,以在子目录中包含Mocs FOT文件。