Qt的元对象编译器(MOC)
- 首先必须知道Qt的信号槽系统是通过元对象编译器moc(Meta-Object Compiler)实现的;
- 听着很懵,但仔细回想一下,再开发工程中是不是都能看到一堆moc_XXXX.cpp的文件,这其实就是Qt元编译器产生的转义中间文件;
- 在Qt工程中,如果类声明中包含Q_OBJECT宏定义,则会生成另外一个moc_XXXX.cpp的C++文件;
emit
跳转到emit的定义,会发现本身就是一个空的宏,也就说,发送信号本质上是执行了一个函数。
Q_OBJECT
- 跳转到Q_OBJECT的定义,有一个关键的静态成员变量staticMetaObject和私有方法qt_static_metacall;
moc文件
QT_INIT_METAOBJECT const QMetaObject XXX::staticMetaObject = { {
QMetaObject::SuperData::link<QWidget::staticMetaObject>(),
qt_meta_stringdata_XXX.data,
qt_meta_data_XXX,
qt_static_metacall,
nullptr,
nullptr
} };
staticMetaObject 这是用来存类的信号、槽、属性等元信息,并且把qt_static_metacall作为函数指针存储起来。由于是静态元对象,所有该类的实例都会共享同一个,不要重复占用内存,减少了开销。
-
qt_static_metacall 用与执行有关的绑定的槽函数或者相关的信号转发 -
qt_meta_data_XXX 用于存储元对象信息,包括信号和槽机制、参数类型信息和一些动态属性 -
qt_meta_stringdata_XXX.data就是存入了访问stringdata0子字符串的指针变量及长度 static const qt_meta_stringdata_XXXX_t qt_meta_stringdata_XXXX:用于存储函数列表及参数信息,内部通过将所有函数拼接成字符串,通过QT_MOC_LITERAL进行字符串的划分;
三个公有方法metaObject、qt_metacast、qt_metacall
- metaObject 用于获取函数的元对象(基本上无需理解,元对象具体是什么,可以看一下QMetaObject的声明)
- qt_metacast 可以在运行时根据字符串名,将当前对象转为相应的基类对象指针,如果转换不成功就是 nullptr
- qt_metacall 这个是调用函数的回调,_c 是元调用方式(QMetaObject::Call ),_id 是属性的绝对序号(Qt对象树顶层QObject到当前方法的索引),_a 是对应需要的需要的参数指针
结论
至此,可能大概对Qt的元编译器有了一个大概了解,也大概明白了Qt信号槽的底层实现(函数回调,只是开发人员几乎无法感知),如果有看不懂的,一定要先了解Qt元对象(QMetaObject)的基础知识。
|