【问题标题】:Unresolved external symbol "public: virtual struct QMetaObject const * __thiscall Parent未解析的外部符号“public: virtual struct QMetaObject const * __thiscall Parent
【发布时间】:2012-12-19 16:42:15
【问题描述】:

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

【问题讨论】:

    标签: c++ qt qobject


    【解决方案1】:

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

    【讨论】:

    • 我遇到了同样的问题。删除调试文件夹没有帮助。还有什么想法吗?
    • @Vern Jensen,检查Q_OBJECT 宏,然后重建,然后删除调试/发布文件夹(删除所有 moc 文件)并再次重建。其中之一应该会有所帮助。
    • 在使用 VS 2012 的 QT5 插件时,从类中删除 Q_OBJECT 宏,保存并添加 Q_OBJECT 再次对我有用
    • 这也解决了我的问题。但为什么以及如何?任何人请解释一下。谢谢!
    • 我在课堂项目中遇到了同样的问题。我发现完全删除Q_OBJECT 宏解决了我的问题。不知道为什么。但如果我把它放回去,我会收到同样的 3 个未解决的错误。我通过在 QT 的 .pro 文件和我正在使用的 cmakelists.txt 文件中包含新类来解决这个问题。一旦我包含了标头和 cpp 文件,代码就可以使用QObject
    【解决方案2】:

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

    【讨论】:

    • 没有其他解决方案对我有用,但确实如此!谢谢! ;)
    • 如果您使用的是 CMake,请确保您拥有 set(CMAKE_AUTOMOC ON)
    • 此答案也应注明为有效答案!
    • 我的锅(VS2017),谢谢。编译时注释掉“Q_OBJECT”,如果恢复则不编译。不会激发对 Qt 的信心。我认为“Q_OBJECT”宏是必要的?
    • 我也在使用 VS 2017。以下发生在我身上:我将 AUTOMOC 添加到我的 CMakeLists 中。这让我的编译器在public signal: 上窒息,这是以前没有的。尽管如此,每当Q_OBJECT 在代码中时,我都会遇到链接器错误,并且运行时错误表明我的自定义类没有定义其他类型。
    【解决方案3】:

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

    此答案基于 Qt Creator。

    与名称所暗示的不同,Rebuild Project 不会清除所有内容并从头开始构建。如果您最近将QObject(和/或Q_OBJECT)添加到您的班级,则必须再次运行qmake,例如

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

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

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

    【讨论】:

    • 太棒了!为我工作。 “运行 qmake”是关键步骤。如果要使用插槽,Q_OBJECT 是必需的。
    【解决方案4】:

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

    【讨论】:

    • 这是在 XCode 中,右键单击“导航器”视图中列出的文件(您的项目使用的文件列表)。
    • 这在 Visual Studio 中也是可能的,但其他人必须告诉你如何在那里配置它。 (我相信你可以在 Qt 的网站上找到答案。)
    • 为了傻笑,我添加了一个头文件和一个 .cpp 文件并将我的 QtObject 派生类移到其中,然后还必须在头文件中#include 并且突然它起作用了。这些东西真的应该记录在某个地方....
    • 为我工作,除了类型是“自定义构建工具”而不是“Qt MOC 输入”。我正在使用 Visual Studio 2017。
    • 在 VS 2019 上它被称为 "Qt Meta-Object Compiler (moc)",当我更改它时为我工作。
    【解决方案5】:

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

    【讨论】:

    • 为什么有必要这样做?
    • 由于 VS 的一些错误配置导致无法使用 moc 文件。有时即使它正确生成了 moc 文件,但由于它们不包含在内,它的行为就像它不存在一样
    【解决方案6】:

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

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

    【讨论】:

      【解决方案7】:

      我在 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 "-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。
      【解决方案8】:

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

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

      【讨论】:

      • 这也是我的问题。不过,不得不在头文件中公开一个内部类很烦人。
      【解决方案9】:

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

      【讨论】:

        【解决方案10】:

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

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

        您应该会找到一个已成功生成的 .h 文件 “moc_*”,复制“Custom Build Tool -> General”中的所有内容 到新的.h文件设置页面。

        注意DebugRelease-Mode 的不同选项。

        之后,构建您的项目。

        DebugRelease-Mode 中各构建一次

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

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

        右键单击它们并更改它们的属性:

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

        【讨论】:

        • 这是一个被低估的答案
        【解决方案11】:

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

        【讨论】:

          【解决方案12】:

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

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

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

          【讨论】:

            【解决方案13】:

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

            【讨论】:

              【解决方案14】:

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

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

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

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

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

              没有进一步解释编码风格,这里是与这个问题相关的重点......为了让Q_OBJECT宏在cpp中工作,让“私有”类成为QObject,它可以使用信号/插槽等.,您需要将 .moc 显式包含到 cpp 内的公共类中

              #include "MyPublicClass.moc"
              

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

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

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

              【讨论】:

                【解决方案15】:

                Visual Studio 2017。

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

                在解决方案资源管理器中右键单击标题 属性... -> 配置属性 -> 常规 -> 项目类型C/C++ Header 更改为 Qt Meta-Object Compiler (moc)

                瞧 :)

                【讨论】:

                  【解决方案16】:

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

                  在原型设计方面,MSVC 肯定会看到 classstruct 之间的区别。

                  希望有一天能帮助别人。

                  【讨论】:

                    【解决方案17】:

                    在我的情况下,以上都不起作用,但这完全是我的错误。

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

                    【讨论】:

                      【解决方案18】:

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

                      #ifndef MYCLASSNAME_H
                      #define MYCLASSNAME_H
                      
                      ... // all the header file content.
                      
                      #endif
                      

                      【讨论】:

                        【解决方案19】:

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

                        【讨论】:

                          【解决方案20】:

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

                          【讨论】:

                            【解决方案21】:

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

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

                            【讨论】:

                              【解决方案22】:

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

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

                              #include "MyClass.h""
                              

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

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

                              【讨论】:

                                【解决方案23】:

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

                                【讨论】:

                                  【解决方案24】:

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

                                  【讨论】:

                                    猜你喜欢
                                    • 2022-08-06
                                    • 2018-11-13
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 2014-05-27
                                    • 1970-01-01
                                    • 2021-04-18
                                    相关资源
                                    最近更新 更多