Qt moc元对象编译器的原理和场景(反射)
Qt Meta-Object Compiler (moc)
元对象编译器,能够实现运行时类型识别。可以用在需要用到反射机制的情况下,qml使用c++的类和方法就是使用了这个特性,通过Q_PROPERTY在类内注册属性;
使用Qt的元对象系统的方法:
-
类要继承自QObject
-
在类申明开始写上Q_OBJECT宏,Q_OBJECT宏的展开为:
static const QMetaObject staticMetaObject; \ virtual const QMetaObject *metaObject() const; \ virtual void *qt_metacast(const char *); \ virtual int qt_metacall(QMetaObject::Call, int, void **); \ Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
moc识别到这个宏之后会编译出moc_youclass.cpp文件,里面有这几个方法和函数的定义和使用;
myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>
class MyClass : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(int size READ size WRITE setSize NOTIFY sizeChanged)
public:
explicit MyClass(QObject *parent = nullptr);
Q_INVOKABLE void PrintSelf();
QString name() const
{
return m_name;
}
size_t size() const
{
return m_size;
}
signals:
void nameChanged(QString name);
void sizeChanged(size_t size);
public slots:
void setName(QString name)
{
if (m_name == name)
return;
m_name = name;
emit nameChanged(m_name);
}
void setSize(size_t size)
{
if (m_size == size)
return;
m_size = size;
emit sizeChanged(m_size);
}
private:
QString m_name;
int m_size;
};
#endif // MYCLASS_H
main.cpp
#include <QCoreApplication>
#include <iostream>
#include <QVariant>
#include <QDebug>
#include <QMetaMethod>
#include "myclass.h"
using namespace std;
void test()
{
cout << "-------test property-----------" << "\n";
MyClass newObj;
newObj.setProperty("type", "fuck");
newObj.setProperty("Member1", 66);
cout << newObj.property( "Member1" ).toString().toStdString() << "\n";
const QMetaObject* mobj = newObj.metaObject();
qDebug() << "obj name = " << mobj->className();
int propertyCount = mobj->propertyCount();
for(int n = 0; n < propertyCount; ++n)
{
qDebug() << "property index : " << n;
QMetaProperty property = mobj->property(n);
qDebug() << "property : " << property.name();
qDebug() << "property value : " << property.read(&newObj);
}
int methodCount = mobj->methodCount();
for(int n = 0; n < methodCount; ++n)
{
qDebug() << "method index : " << n;
QMetaMethod method = mobj->method(n);
qDebug() << "method name : " << method.name();
method.invoke(&newObj);
}
QMetaObject::invokeMethod( &newObj, "PrintSelf", Qt::DirectConnection);
MyClass* myClass = dynamic_cast<MyClass*>(mobj->newInstance());
cout << "--------end----------" << "\n";
}
int main(int argc, char *argv[])
{
test();
QCoreApplication a(argc, argv);
return a.exec();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?