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
解决方法
- 当
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之前。
- 当
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时注意不要包含非英文路径。
###进一步阅读
本文详细介绍了在使用Qt的元对象编译器MOC时遇到的宏展开问题,问题源于包含中文路径的头文件导致宏未正确展开。通过对比英文路径下的正确展开情况,分析了问题原因,并提供了避免使用非英文路径的解决方案,以确保MOC能正确处理宏定义。
1237

被折叠的 条评论
为什么被折叠?



