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时注意不要包含非英文路径。
###进一步阅读