在 Qt 中,元对象(Meta-Object) 是元对象系统的核心组件,它使 Qt 能够提供强大的特性如信号槽机制、运行时类型信息(RTTI)和动态属性系统。
元对象是一个特殊的静态数据结构,它在运行时提供关于类的详细信息:
// QMetaObject 定义(简化)
struct QMetaObject {
const char *className; // 类名
const QMetaObject *superClass; // 父类元对象
int methodCount; // 方法数量
int propertyCount; // 属性数量
int enumeratorCount; // 枚举数量
const QMetaMethod *methods; // 方法数组
const QMetaProperty *properties; // 属性数组
// ... 其他元数据
};
// QMetaMethod 结构(简化)
struct QMetaMethod {
QMetaMethod::MethodType methodType; // 信号、槽、方法等
const char *name; // 方法名
const char *typeName; // 返回类型
int parameterCount; // 参数数量
const char **parameterTypes; // 参数类型数组
};
// QMetaProperty 结构(简化)
struct QMetaProperty {
const char *name; // 属性名
const char *typeName; // 属性类型
bool isReadable; // 是否可读
bool isWritable; // 是否可写
bool isDesignable; // 设计时可用
};
// QMetaEnum 结构(简化)
struct QMetaEnum {
const char *name; // 枚举名
int keyCount; // 键数量
const char **keys; // 键名数组
int *values; // 键值数组
};
编译阶段:
Q_OBJECT
的类moc_*.cpp
文件,包含:// 自动生成的元对象
static const QMetaObject staticMetaObject = {
{ &ParentClass::staticMetaObject }, // 父类元对象
"MyClass", // 类名
method_data, // 方法数据
property_data, // 属性数据
// ...
};
运行时阶段:
metaObject()
访问元对象const QMetaObject *meta = obj->metaObject();
qDebug() << "Class:" << meta->className();
// 信号槽连接示例
QObject::connect(sender, &Sender::valueChanged,
receiver, &Receiver::updateValue);
// 底层实现
QMetaObject::Connection QObject::connect(
const QObject *sender, const char *signal,
const QObject *receiver, const char *method);
// 添加动态属性
obj->setProperty("priority", 5);
// 获取动态属性
int priority = obj->property("priority").toInt();
// 获取所有属性
const QMetaObject *meta = obj->metaObject();
for(int i=0; i<meta->propertyCount(); ++i) {
QMetaProperty prop = meta->property(i);
qDebug() << prop.name() << ":" << prop.read(obj);
}
// 动态调用方法
QMetaObject::invokeMethod(obj, "calculate",
Qt::DirectConnection,
Q_ARG(int, 5),
Q_RETURN_ARG(double, result));
// 跨线程通信
QMetaObject::invokeMethod(worker, "processData",
Qt::QueuedConnection,
Q_ARG(QByteArray, data));
// 根据类名创建控件
QWidget* createWidget(const QString &className) {
const QMetaObject *mo = QMetaType::metaObjectForName(className.toUtf8());
if(mo) {
return qobject_cast<QWidget*>(mo->newInstance());
}
return nullptr;
}
// 保存对象状态
void saveState(QObject *obj, QSettings &settings) {
const QMetaObject *mo = obj->metaObject();
for(int i=0; i<mo->propertyCount(); ++i) {
QMetaProperty prop = mo->property(i);
if(prop.isStored()) {
settings.setValue(prop.name(), prop.read(obj));
}
}
}
// 暴露对象到 JavaScript
QWebEngineView view;
QWebChannel *channel = new QWebChannel(view.page());
channel->registerObject("appObject", myObject);
view.page()->setWebChannel(channel);
虽然元对象系统带来一定开销,但 Qt 通过以下方式优化:
Qt 的元对象系统是其框架的核心支柱,通过元对象实现了:
正是元对象系统使 Qt 能够超越标准 C++ 的限制,提供更高级别的抽象和更强大的功能,同时保持类型安全和性能效率。