VS2015 + QT 编译出现public: virtual struct QMetaObject const * __thiscall 错误

22 篇文章 ¥9.90 ¥99.00
在使用VS2015编译QT项目时遇到错误LNK2001,无法解析TDECTitleWidget的metaObject。解决方法是通过在QT安装目录的bin下运行moc命令,针对出错的头文件生成moc_XXX.cpp文件,并将其拷贝到工程的GeneratedFiles目录下,从而解决编译问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

VS2015 编译QT项目出现错误:

严重性    代码    说明    项目    文件    行    禁止显示状态

错误    LNK2001    无法解析的外部符号 "public: virtual struct QMetaObject const * __thiscall TDECTitleWidget::metaObject(void)const " (?metaObject@TDECTitleWidget@@UBEPBUQMetaObject@@XZ)    TDECView    E:\QTProject\TDECView\TDECTitleWidget.obj    1


解决方法: 

cmd 运行到 QT 安装目录

D:\InsallPackages\Qt\Qt5.7.1\5.7\msvc2015\bin


这里首先查看出错的文件是哪一个, 然后生成文件,执行下面的语句:

moc "E:\QTProject\Test\MainMenu.h" -o "E:\Test\TDECView\moc_MainMenu.cpp"


将会在工程目录产生一个文件 moc_MainMenu.cpp


拷贝moc_MainMenu.cpp 文件到 E:\QTProject\Test\GeneratedFiles\Debug

目录下就可以解决这个问题


1>libqrencode.lib(qrencode.obj) : 找到 MSIL .netmodule 或使用 /GL 编译的模块;正在使用 /LTCG 重新启动链接;将 /LTCG 添加到链接命令行以改进链接器性能 1>DrawModeCheckDialog.obj : error LNK2001: 无法解析的外部符号 "public: virtual struct QMetaObject const * __thiscall DrawModeCheckDialog::metaObject(void)const " (?metaObject@DrawModeCheckDialog@@UBEPBUQMetaObject@@XZ) 1>DrawModeCheckDialog.obj : error LNK2001: 无法解析的外部符号 "public: virtual void * __thiscall DrawModeCheckDialog::qt_metacast(char const *)" (?qt_metacast@DrawModeCheckDialog@@UAEPAXPBD@Z) 1>DrawModeCheckDialog.obj : error LNK2001: 无法解析的外部符号 "public: virtual int __thiscall DrawModeCheckDialog::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@DrawModeCheckDialog@@UAEHW4Call@QMetaObject@@HPAPAX@Z) 1>NCApplication.obj : error LNK2001: 无法解析的外部符号 "public: virtual struct QMetaObject const * __thiscall NCApplication::metaObject(void)const " (?metaObject@NCApplication@@UBEPBUQMetaObject@@XZ) 1>NCApplication.obj : error LNK2001: 无法解析的外部符号 "public: virtual void * __thiscall NCApplication::qt_metacast(char const *)" (?qt_metacast@NCApplication@@UAEPAXPBD@Z) 1>NCApplication.obj : error LNK2001: 无法解析的外部符号 "public: virtual int __thiscall NCApplication::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@NCApplication@@UAEHW4Call@QMetaObject@@HPAPAX@Z) 1>NCApplication.obj : error LNK2001: 无法解析的外部符号 "public: static struct QMetaObject const NCApplication::staticMetaObject" (?staticMetaObject@NCApplication@@2UQMetaObject@@B) 1>sliderStepButton.obj : error LNK2001: 无法解析的外部符号 "public: virtual struct QMetaObject const * __thiscall sliderStepButton::metaObject(void)const " (?metaObject@sliderStepButton@@UBEPBUQMetaObject@@XZ) 1>sliderStepButton.obj : error LNK2001: 无法解析的外部符号 "public: virtual void * __thiscall sliderStepButton::qt_metacast(char const *)" (?qt_metacast@sliderStepButton@@UAEPAXPBD@Z) 1>sliderStepButton.obj : error LNK2001: 无法解析的外部符号 "public: virtual int __thiscall sliderStepButton::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@sliderStepButton@@UAEHW4Call@QMetaObject@@HPAPAX@Z) 1>E:\lyf-Qt\laser\QtVisionLaser\Win32\Debug\\LaserVision.exe : fatal error LNK1120: 10 个无法解析的外部命令 怎么查看哪些头文件需要手动编译
06-22
<think>首先,用户的问题是关于C++QMetaObject的虚函数metaObject的声明和用途。具体来说,是理解这个声明:'public: virtual struct QMetaObject const * __cdecl computerInfoPost::metaObject(void)const'。 我需要参考系统级指令: - 所有行内数学表达式使用$...$,但这里可能没有数学表达式。 - 独立公式使用$$...$$,但这个问题可能不涉及数学公式。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识。 - 回答结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 用户提供的引用: - [^1]: 关于LZ4_stream_t的错误声明。 - [^2]: 关于Q_OBJECT宏的缺失错误和解释。 - [^3]: 关于connect函数的错误。 这些引用似乎与用户当前的问题相关,但不是直接针对QMetaObject的metaObject函数。用户说“上述引用仅供参考”,所以我应该基于问题内容回答,而不是这些引用。 关键问题:理解QMetaObject中的虚函数metaObject的声明和用途。 在Qt中,QMetaObject是一个核心类,用于元对象系统。metaObject函数是QObject类中的一个虚函数,用于返回对象的元对象指针。 声明:'public: virtual struct QMetaObject const * __cdecl computerInfoPost::metaObject(void)const' 解析声明: - public: 访问修饰符,表示公共访问。 - virtual: 表示这是一个虚函数。 - struct QMetaObject const *: 返回类型是一个指向常量QMetaObject结构的指针。 - __cdecl: 调用约定,在Windows上常见,表示C调用约定。 - computerInfoPost::metaObject: 函数名,属于computerInfoPost类。 - (void): 参数列表为空。 - const: 函数是常量成员函数,不会修改对象状态。 用途: - metaObject函数用于获取对象的元对象指针。 - 元对象包含类的元信息,如类名、属性、信号、槽等。 - 在Qt的信号槽机制、属性系统、动态类型检查中,这个函数至关重要。 - 当类使用Q_OBJECT宏时,Qtmoc(元对象编译器)会生成这个函数的实现。 参考用户提供的引用[^2],它强调了Q_OBJECT宏的重要性,这与metaObject函数直接相关。因为如果没有Q_OBJECT宏,metaObject函数可能不会被正确实现。 步骤式回答: 1. **解释声明**:分解声明部分。 2. **用途**:描述函数的作用。 3. **如何工作**:简要说明在Qt中如何实现。 4. **常见问题**:如为什么需要虚函数等。 生成相关问题: - 基于内容,生成3个相关问题。 回答结构: - 清晰、分步。 - 使用中文。 - 自然地添加引用标识。 最终回答大纲: 1. 介绍QMetaObject和metaObject函数。 2. 解析声明。 3. 解释用途。 4. 讨论与Q_OBJECT宏的关系。 5. 生成相关问题。</think>### 理解QMetaObject中虚函数metaObject的声明和用途 在Qt框架中,`QMetaObject` 是元对象系统(Meta-Object System)的核心组件,用于提供运行时类型信息(RTTI)、信号槽机制和属性系统。虚函数 `metaObject()` 是 `QObject` 类中的一个关键成员函数,它在所有派生类中被重写以实现动态反射功能。以下我将逐步解析您提供的声明 `'public: virtual struct QMetaObject const * __cdecl computerInfoPost::metaObject(void)const'`,并解释其用途。 #### 1. **声明解析** - **声明分解**: - `public`: 访问修饰符,表示该函数是公共的,可以从任何地方访问。 - `virtual`: 关键字表示这是一个虚函数,允许派生类重写(override)它以实现多态行为。在Qt中,这确保了运行时动态绑定。 - `struct QMetaObject const *`: 返回类型是一个指向常量 `QMetaObject` 结构体的指针。`const` 修饰符表示返回的指针指向的对象不可修改,确保元数据的安全性。 - `__cdecl`: 调用约定(calling convention),指定函数参数的传递方式。`__cdecl` 是C/C++标准调用约定,常见于Windows平台,表示参数从右向左压栈,调用者负责清理栈。 - `computerInfoPost::metaObject`: 函数名和所属类。这里 `computerInfoPost` 是您的自定义类(继承自 `QObject`),`metaObject` 是函数名。 - `(void)`: 参数列表为空,表示该函数不接受任何参数。 - `const`: 修饰成员函数,表示该函数不会修改类的任何成员变量(即常量成员函数)。 - **完整含义**: 该声明定义了一个公共虚函数,属于 `computerInfoPost` 类,返回一个指向常量 `QMetaObject` 的指针,不接受参数,且不会改变对象状态。 这个函数通常由Qt的元对象编译器(moc)自动生成,前提是类声明中包含 `Q_OBJECT` 宏。如果没有这个宏,编译器可能无法生成正确的实现,导致运行时错误[^2]。 #### 2. **用途和功能** `metaObject()` 函数的主要用途是提供对象的元数据,支持Qt的反射机制。以下是其核心功能: - **获取元对象信息**: 返回的 `QMetaObject` 指针包含类的元数据,例如: - 类名(通过 `className()` 方法)。 - 信号和槽的列表(用于信号槽连接)。 - 属性信息(如名称、类型和可读/写状态)。 - 枚举和方法的元数据。 - **支持信号槽机制**: 在信号槽连接中(如 `QObject::connect()`),Qt 使用 `metaObject()` 动态查找信号和槽的索引。如果元对象信息缺失,连接可能失败并报错[^3]。 - **实现动态类型检查**: 通过 `qobject_cast` 或 `inherits()` 函数,可以在运行时安全地转换对象类型。 - **启用属性系统**: 允许通过 `property()` 和 `setProperty()` 方法动态访问和修改对象的属性。 - **应用场景**: 常用于GUI编程(如Qt Widgets)、序列化(如保存对象状态到文件)和插件系统,其中需要运行时查询和操作对象。 在您的声明中,`computerInfoPost::metaObject()` 确保了 `computerInfoPost` 类能无缝集成Qt的元对象系统。如果该类未声明 `Q_OBJECT` 宏,`metaObject()` 可能返回错误或不完整的元数据,导致信号槽连接失败或其他运行时问题[^2]。 #### 3. **工作流程示例** 当您定义一个Qt类时: - **步骤1**: 在类声明中添加 `Q_OBJECT` 宏,例如: ```cpp class computerInfoPost : public QObject { Q_OBJECT // 必需,以生成元对象代码 public: virtual const QMetaObject *metaObject() const override; // moc自动实现 // ... 其他成员 }; ``` - **步骤2**: Qtmoc工具在编译前处理源文件,生成一个 `moc_*.cpp` 文件,其中包含 `metaObject()` 的实现。该实现返回一个静态的 `QMetaObject` 实例,存储类的元信息。 - **步骤3**: 在运行时,调用 `obj->metaObject()` 获取元数据指针,用于动态操作: ```cpp const QMetaObject *meta = obj->metaObject(); qDebug() << "Class name:" << meta->className(); // 输出类名 ``` #### 4. **常见问题与注意事项** - **为什么需要虚函数?** 虚函数允许每个派生类提供自己的元对象实现,支持多态。如果不使用 `virtual`,基类指针调用时可能无法正确获取派生类的元数据。 - **错误处理**: 如果忘记添加 `Q_OBJECT` 宏,`metaObject()` 可能返回基类的元对象(如 `QObject` 的默认实现),导致信号槽或属性访问失败[^2]。编译错误通常类似 "undefined reference to `vtable`"。 - **性能考虑**: `metaObject()` 调用是高效的,因为它返回一个预编译的静态指针,开销很小。 总之,`metaObject()` 函数是Qt元对象系统的基石,通过提供运行时反射能力,简化了动态对象操作。确保正确使用 `Q_OBJECT` 宏是避免相关错误的关键[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飛越無限

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值