我从 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)
您应该删除应用程序的 debug
文件夹并再次运行它以更正此问题。
如果您使用的是 Visual Studio,请从头文件中删除行 Q_OBJECT
,保存文件,将 Q_OBJECT
放回头文件,再次保存文件。这应该会生成 moc_*
文件并且应该正确构建和链接。
set(CMAKE_AUTOMOC ON)
public signal:
上窒息,这是以前没有的。尽管如此,每当代码中出现 Q_OBJECT
时,我都会遇到链接器错误,并且运行时错误表明我的自定义类未定义其他类型。
我注意到一些答案是基于 Visual Studio 的。
这个答案基于 Qt Creator。
与名称所暗示的不同,Rebuild Project
不会清除所有内容并从头开始构建。如果您最近将 QObject
(和/或 Q_OBJECT)添加到您的课程中,则必须再次运行 qmake
,例如
清理项目运行 qmake 构建项目
这是因为,默认情况下,qmake
仅在您对解决方案进行重大更改(例如添加新源文件或修改 .pro
文件)时运行。如果您对现有文件进行编辑,它不知道它需要运行 qmake
。
作为后备,要强制 Qt 从头开始构建所有内容,请删除 Debug
或 Release
文件夹。
所以问题是我需要 Qt MOC 编译器来编译我的 .h 文件。这对于扩展 QObject 或其子之一的任何类都是必需的。修复涉及(对我而言)右键单击头文件,选择属性,并将项目类型设置为“Qt MOC 输入”,然后在头上点击“编译”,然后将生成的 moc_myfilename.cpp 文件添加到我的项目。
"Qt Meta-Object Compiler (moc)"
,当我更改它时对我有用。
我手动将 cpp/ui 文件添加到我的项目中,但忘记将头文件显式添加为头文件。现在,在编译时,我收到了与上面类似的错误消息,并且 moc_*.cpp 文件未在构建的调试(或发布)目录中生成。这不是一个明显的错误,qmake 没有抱怨,除了链接器消息之外我没有收到任何错误。
因此,如果有人再次遇到同样的问题(或犯同样的复制和粘贴错误):确保头文件也已添加到您的项目文件中
如果您的 moc 文件是在 Visual Studio 项目中生成的,请尝试将它们包含到项目中,如果它们未包含在项目中,则重新构建。
我在 Visual Studio 中遇到了同样的问题,并通过以下步骤解决了它:
在解决方案资源管理器属性中右键单击头文件将“项目类型”更改为“自定义构建工具”
然后在自定义构建工具配置中:
转到常规,将“命令行”设置为:“$(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_FINDEBUG_FINEDH=7 "-I.\SFML_STATIC" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)。" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" 将“输出”设置为:.\GeneratedFiles\$(ConfigurationName) \moc_%(Filename).cpp 将“附加依赖项”设置为:$(QTDIR)\bin\moc.exe;%(FullPath)
您的确切值可能不同。它们通常通过 Qt 插件应用。
当我的 cpp 文件中有 Q_OBJECT 类定义时,我在 Visual Studio 2012 中遇到了这个问题。将类定义移动到头文件解决了这个问题。
看起来应该可以通过将 cpp 文件添加到 moc 来支持 cpp 文件中的 Q_OBJECT 类,但我没有尝试过。
我使用 CMake 来管理 Qt 项目,并且需要在 QT4_WRAP_CPP 调用下添加新的 Q_OBJECT。这将生成 moc_*.cxx 以包含在项目中并清理未解析的外部。
我的问题是我的一个使用 Qt 宏的文件没有被 moc'ed。我发现用于 Visual Studio 的 Qt 插件无法识别 Q_NAMESPACE
宏,因此不会将文件添加到 moc'ing 列表中。
所以我使用 this answer 中的解决方案将文件添加到麦克风列表:
您应该找到一个成功生成“moc_*”的.h文件,并将“自定义构建工具->常规”中的所有内容复制到新的.h文件设置页面。
请注意 Debug
和 Release
-Mode 的不同选项。
之后,构建您的项目。
在 Debug
和 Release
-Mode 中各构建一次
最后,将生成的“moc_*”文件添加到您的项目中。
现在,“moc_filename.cpp”应该在 Generated Files\Debug
和 Generated Files\Release
中。
右键单击它们中的每一个并更改它们的属性:
Debug 中的文件:将配置更改为 Release,然后将 General->Excluded 从 build 更改为 yes。
Release 中的文件:将配置更改为 Debug,然后将 General->Excluded 从 build 更改为 yes。
在链式 CMake 目标的情况下面临此问题。事实证明,即使在不直接(传递)使用 Qt 的目标中,我也必须启用 CMAKE_AUTOMOC
。还发现 CMAKE_AUTOMOC
不能在没有 find_package(QtX)
的情况下在父级的同一 CMakeLists.txt
或 CMakeLists.txt
中使用。
就我而言(将 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 行为。
将 QtAdd-in 与 VS2010 一起使用,我意识到 moc_*.cpp 文件已在 GeneratedFiles/Debug 文件夹中更新,尽管我处于发布模式。将文件复制到 Release 文件夹对我有用。
我知道这是一个非常古老的问题,但它似乎仍然很有趣(过去几个月我至少来过这里 4 或 5 次)并且似乎我找到了另一个可能导致此错误的原因。
在我的头文件中,我输入错误:
#include "MyClass.h""
只有在检查了整个输出之后,我才发现编译器在那一行发出了警告。
现在我删除了额外的引号,我的 QObject 可以完美编译!
在使用“PIMPL”(私有实现)编程模式时,我在 Qt 中使用“私有类”时遇到了这个问题。 Qt 在整个源代码中都使用了这个模型。我自己已经非常喜欢它了。
这种技术涉及在公共头文件中使用“私有”前向声明的类,该类将被“公共”类(即它的“父”)使用。然后父级有一个指向私有类实例的指针作为数据成员。
“私有”类完全在公共类的 cpp 文件中定义。私有类没有头文件。
所有“肮脏的工作”都是通过该私人课程完成的。这隐藏了公共类的所有实现,通常包括所有其他私有成员(数据和函数)。
我强烈建议您学习 PIMPL 模式——尤其是如果您要阅读内部 Qt 源代码。
在不进一步解释该编码风格的情况下,这里是与此问题相关的要点...要使 Q_OBJECT
宏在 cpp 内工作,以使“私有”类成为可以使用信号/插槽等的 QObject,< strong>您需要将 .moc 明确包含在 cpp 中的公共类中:
#include "MyPublicClass.moc"
您可以忽略有关此行的任何 IDE 警告。
我不确定它是否完全重要,但我总是看到在私有类定义之后完成的包含,而不是在 cpp 的顶部(就像通常放置的包含一样)。因此,cpp 布局如下所示:
“正常”包括已定义。定义了私有类。公共类的 moc 是#included。定义了公共类实现。
视觉工作室 2017。
我已将文件添加到已设置 Qt 项目并收到此错误。我如何修复它:
右键单击解决方案资源管理器属性中的标题... -> 配置属性 -> 常规 -> 项目类型从 C/C++ 标题更改为 Qt 元对象编译器(moc)
瞧:)
我最近从 MingW 切换到 MSVC 时发生了这种情况。我有一个原型类/结构列为类,MingW 不介意。
当涉及到原型设计时,MSVC 肯定会发现 class
和 struct
之间的区别。
希望有一天能帮助别人。
就我而言,上述方法均无效,但这完全是我的错误。
我在 .h 文件中覆盖了虚函数(声明了它们),但从未在 .cpp 中定义它们 :)
我通过将其添加到我的头文件中解决了我的问题:
#ifndef MYCLASSNAME_H
#define MYCLASSNAME_H
... // all the header file content.
#endif
在 VS 2013 环境中,任何一个答案都适用于我。我最终通过从项目中删除 .h/.cpp 并将其添加回来来解决问题。
我正在使用集成的 Perforce p4v 客户端在 VS2015 中工作。就我而言,Perforce 尝试将 moc 文件添加到 depo,当我恢复此操作时,Perforce 从项目中删除了这个 moc 文件并将其删除。该文件在下一次编译后重新创建,但它没有包含在项目中,我必须手动将其添加到生成的文件中,当我终于明白问题出在哪里时。
我有同样的问题,我的解决方案是编码(我的带有“UTF16LE BOM”的文件不能用 moc.exe 生成),你创建另一个带有 ASCII 编码的文件并且它可以工作。
HxD HexEditor 可以帮助您查看编码。
对我来说,这就是原因:QT的项目文件中没有包含一些头文件或源文件
在我的情况下,我在项目的子文件夹中有问题 QObject 祖先的 .h 和 .cpp 文件。当我将它们移到 CMakeLists.txt(项目根文件夹)旁边时,它成功链接。我可能缺少一些 CMake 命令来在子目录中包含 mocs fot 文件。
当我删除 Q_OBJECT 它工作正常。
我正在使用 Clion + CMake + MSVC/14.31.31103。
是因为在这些之后不再需要 Q_OBJECT 吗?
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
Q_OBJECT
宏,然后重建,然后删除调试/发布文件夹(以删除所有 moc 文件)并再次重建。其中之一应该会有所帮助。Q_OBJECT
宏解决了我的问题。不知道为什么。但如果我把它放回去,我会收到同样的 3 个未解决的错误。我通过在 QT 的.pro
文件和我正在使用的cmakelists.txt
文件中包含新类来解决这个问题。一旦我包含了标头和 cpp 文件,代码就可以使用QObject
。