Qt原对象metaObject编译错误的问题

本文详细介绍了在使用Qt的元对象编译器MOC时遇到的宏展开问题,问题源于包含中文路径的头文件导致宏未正确展开。通过对比英文路径下的正确展开情况,分析了问题原因,并提供了避免使用非英文路径的解决方案,以确保MOC能正确处理宏定义。

MOC(Meta-Object Complier)

关于元对象编译器的作用可参考文章:qt中moc的作用

MOC宏展开

问题描述

编译由元对象编译器生成的 moc_filename.cpp 文件时,报错

ClassName': is not a class or namespace name

错误定位于代码

void ClassName::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)

其中,使用Qt的头文件filename.h中包含由宏定义的多层命名空间

#pragma once
#include <QWidget>
#include "common_def.h"
TEST_NAMESPACE_BEGIN
class MacroExpand : public QWidget
{
    Q_OBJECT
public:
    MacroExpand(QWidget *parent = Q_NULLPTR);
    ~MacroExpand();
private:
};
TEST_NAMESPACE_END

宏定义于common_def.h

#define TEST_NAMESPACE_BEGIN namespace ns1 { namespace ns2 { namespace ns3 {
#define TEST_NAMESPACE_END }}}

测试环境:

Qt Community 5.10.1 + VS2013
Qt Community 5.14.1 + VS 2019

解决方法

  1. filename.h完整路径包含中文如moc_macro_expanding\宏展开测试时,元编译生成的moc_xx.cpp文件片段为:
void MacroExpand::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
    Q_UNUSED(_o);
    Q_UNUSED(_id);
    Q_UNUSED(_c);
    Q_UNUSED(_a);
}

QT_INIT_METAOBJECT const QMetaObject MacroExpand::staticMetaObject = { {
    QMetaObject::SuperData::link<QWidget::staticMetaObject>(),
    qt_meta_stringdata_MacroExpand.data,
    qt_meta_data_MacroExpand,
    qt_static_metacall,
    nullptr,
    nullptr
} };

可以看出宏定义TEST_NAMESPACE_BEGIN, TEST_NAMESPACE_END并未展于MacroExpand::staticMetaObject之前。

  1. filename.h完整路径纯英文如moc_macro_expanding\moc_macro_expanding时,元编译生成的moc_xx.cpp文件片段为
void ns1::ns2::ns3::MacroExpand::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
    Q_UNUSED(_o);
    Q_UNUSED(_id);
    Q_UNUSED(_c);
    Q_UNUSED(_a);
}

QT_INIT_METAOBJECT const QMetaObject ns1::ns2::ns3::MacroExpand::staticMetaObject = { {
    QMetaObject::SuperData::link<QWidget::staticMetaObject>(),
    qt_meta_stringdata_ns1__ns2__ns3__MacroExpand.data,
    qt_meta_data_ns1__ns2__ns3__MacroExpand,
    qt_static_metacall,
    nullptr,
    nullptr
} };

宏定义ns1::ns2::ns3::被正确展开,进而编译moc_xx.cpp便不会出现前述问题。

原因分析

尚缺TODO

总结

使用Qt时注意不要包含非英文路径。

###进一步阅读

  1. Macro expansion in moc
  2. C++ Preprocessor and QT MOC
  3. Force Moc to moc a file
在使用 CMake 构建 Qt 项目时,遇到与 Meta-Object Compiler (moc) 相关的错误通常与构建系统配置不当或源文件未正确声明有关。以下是一些常见的解决方法和建议: ### 1. 确保正确使用 `Q_OBJECT` 宏 如果一个类使用了信号和槽机制、动态属性或反射功能,则必须在其类定义中添加 `Q_OBJECT` 宏。这是触发 `moc` 生成元对象代码的前提条件。若未添加该宏,将导致编译失败或链接错误。 ```cpp class MyClass : public QObject { Q_OBJECT // 必须添加此宏 public: explicit MyClass(QObject *parent = nullptr); signals: void mySignal(); public slots: void mySlot(); }; ``` ### 2. 确保 CMake 正确配置 Qt 模块 在 `CMakeLists.txt` 文件中,确保已正确配置 Qt 模块,并启用 `AUTOMOC` 功能。现代 CMake(3.14+)支持自动调用 `moc`,无需手动指定。 ```cmake cmake_minimum_required(VERSION 3.14) project(MyQtProject) set(CMAKE_CXX_STANDARD 17) find_package(Qt5 COMPONENTS Core Widgets REQUIRED) add_executable(MyQtProject main.cpp mainwindow.cpp) target_link_libraries(MyQtProject PRIVATE Qt5::Core Qt5::Widgets) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUI ON) ``` ### 3. 检查 `moc_` 文件是否生成 构建过程中,`moc` 会生成以 `moc_` 开头的 C++ 文件(如 `moc_myclass.cpp`)。如果这些文件未生成,可能是因为类未正确声明 `Q_OBJECT`,或者构建系统未识别到需要处理的类。 ### 4. 确保所有使用 `Q_OBJECT` 的类被正确包含在 `add_executable()` 或 `add_library()` 中 如果某个类使用了 `Q_OBJECT`,但未被包含在目标构建中(如 `add_executable()` 或 `add_library()`),则 `moc` 可能无法正确处理该类。 ```cmake add_executable(MyQtProject main.cpp myclass.cpp) ``` ### 5. 使用 `qt5_wrap_cpp()`(适用于旧版本 CMake) 在某些旧版本的 CMake 中,可能需要显式调用 `qt5_wrap_cpp()` 来生成 `moc` 文件。 ```cmake qt5_wrap_cpp(MOC_SOURCES myclass.h) add_executable(MyQtProject main.cpp ${MOC_SOURCES}) ``` ### 6. 清理并重新构建项目 有时旧的构建文件可能导致问题,建议执行以下步骤: ```bash rm -rf build/ mkdir build cd build/ cmake .. make ``` ### 7. 检查头文件路径和依赖关系 如果头文件路径配置错误,`moc` 可能无法找到所需的类定义文件。确保 `include_directories()` 正确设置,并且所有依赖项已正确声明。 ```cmake include_directories(${PROJECT_SOURCE_DIR}/include) ``` ### 8. 避免手动包含 `moc_` 文件 除非特殊需要,否则不建议手动包含 `moc_` 文件(如 `#include "moc_myclass.cpp"`)。现代 CMake 会自动处理这些文件,手动包含可能导致重复定义错误。 ### 9. 查看具体错误信息并针对性处理 CMake 错误信息通常会指出问题所在。例如: - `moc: No such file or directory`:表示 `moc` 可执行文件未找到,需检查 Qt 安装路径和环境变量。 - `undefined reference to vtable for MyClass`:表示 `moc` 未生成对应的元对象代码,需检查 `Q_OBJECT` 是否声明或是否被正确编译---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值