LNK2001: virtual struct QMetaObject const 错误的解决方法和原因

目录

1.现象

2.原因分析

3.解决方法

3.1.方法1

3.2.方法2


1.现象

今天调整了下工程目录结构(环境是VS2019+Qt5.12.12),重新编译突然出现以下错误:

没有修改代码,怎么就出现这个错误了呢?从上面的错误来看,其实就是找不到报错函数的实现

2.原因分析

从错误分析出现这个错误大概率估计还是信号槽的原因,只有继承了QObject类的类,才具有信号槽的能力。所以,为了使用信号槽,必须继承QObject。凡是QObject类(不管是直接子类还是间接子类),都应该在第一行代码写上Q_OBJECT。不管是不是使用信号槽,都应该添加这个宏。这个宏的展开将为我们的类提供信号槽机制、国际化机制以及 Qt 提供的不基于 C++ RTTI 的反射能力。因此,如果你觉得你的类不需要使用信号槽,就不添加这个宏,就是错误的。其它很多操作都会依赖于这个宏。注意,这个宏将由 moc(我们会在后面章节中介绍 moc。这里你可以将其理解为一种预处理器,是比 C++ 预处理器更早执行的预处理器。) 做特殊处理,不仅仅是宏展开这么简单。moc 会读取标记了 Q_OBJECT 的头文件,生成以 moc_ 为前缀的文件,比如 newspaper.h 将生成 moc_newspaper.cpp。你可以到构建目录查看这个文件,看看到底增加了什么内容。注意,由于 moc 只处理头文件中的标记了Q_OBJECT的类声明,不会处理 cpp 文件中的类似声明。因此,如果我们的NewspaperReader类位于 main.cpp 中,是无法得到 moc 的处理的。解决方法是,我们手动调用 moc 工具处理 main.cpp,并且将 main.cpp 中的#include "newspaper.h"改为#include "moc_newspaper.h"就可以了。不过,这是相当繁琐的步骤,为了避免这样修改,我们还是将其放在头文件中。许多初学者会遇到莫名其妙的错误,一加上Q_OBJECT就出错,很大一部分是因为没有注意到这个宏应该放在头文件中。

3.解决方法

3.1.方法1

1)首先查看源代码中继承QObject的类是否添加了Q_OBJECT,没有则添加Q_OBJECT,如:

BaseUnits.h

2)然后在工程编译结果目录下,一般都会生成一个moc文件夹,里面存放编译过程中生成的临时文件, 命名大都是 moc_xxxx.cpp这样,如:

如果没有这个文件,需要利用moc.exe生成BaseUnits.cpp文件,在cmd下执行下面操作,注意BaseUnits.h和moc_BaseUnits.cpp的文件路径

moc_BaseUnits.cpp生成完毕。

3)拷贝moc_BaseUnits.cpp到上述moc目录下,重新编译即可

3.2.方法2

网上的方法,我也不知道为什么?方法如下:

删掉头文件的 Q_OBJECT 重新生成

如果后面还报错,就再添加Q_OBJECT ,再重新生成

相关推荐
_OP_CHEN3 分钟前
【从零开始的Qt开发指南】(二十一)Qt 网络编程封神指南:UDP/TCP/HTTP 全场景实战
网络·qt·http·udp·tcp·前端开发·qt网络
王老师青少年编程5 分钟前
2025年12月GESP真题及题解(C++八级): 宝石项链
c++·gesp·csp·信奥赛·八级·csp-s·提高组
郝学胜-神的一滴6 分钟前
深入理解Qt中的坐标系统:鼠标、窗口与控件位置详解
开发语言·c++·qt·程序人生
福楠6 分钟前
C++ | 继承
c语言·开发语言·数据结构·c++·算法
程序员zgh8 分钟前
汽车以太网协议 —— DDS
c语言·开发语言·c++·网络协议·udp·汽车·信息与通信
superman超哥9 分钟前
Rust 异步编程的终极考验:Tokio 资源管理与清理
开发语言·rust·编程语言·rust异步编程·tokio资源管理与清理
王老师青少年编程9 分钟前
2025年12月GESP真题及题解(C++八级): 猫和老鼠
c++·gesp·csp·信奥赛·八级·csp-s·提高组
前天的五花肉10 分钟前
D3.js研发交互模型指标柱形图
开发语言·javascript·交互
你怎么知道我是队长11 分钟前
C语言---强制类型转换
c语言·开发语言·算法
_OP_CHEN11 分钟前
【算法基础篇】(四十六)同余方程终极攻略:从基础转化到实战破解
c++·算法·蓝桥杯·数论·同余方程·扩展欧几里得算法·acm/icpc