Qt框架浅析之三 ------ Qt元对象系统(一)

    元对象系统涉及很多方面,比如运行时类信息,属性信息,信号槽等等,但是其中最主要的应该是信号槽,大家也许在处理信号槽的时候都碰到过这么一个问题:为什么我没加Q_OBJECT宏,信号槽就生效不了呢?进入正题:

#define Q_OBJECT \
public: \
    Q_OBJECT_CHECK \
    static const QMetaObject staticMetaObject; \
    virtual const QMetaObject *metaObject() const; \
    virtual void *qt_metacast(const char *); \
    QT_TR_FUNCTIONS \
    virtual int qt_metacall(QMetaObject::Call, int, void **); \
private: \
    Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
    struct QPrivateSignal {};

    元对象系统涉及到的主要的实现类:QMataClassInfo, QMetaEnum, QMetaDataReaderControl, QMetaObject, QMetaProperty, QMetaType,我会在之后的博文中介绍这几个类的作用。

    即使是最简单只有一个信号和槽函数的头文件的moc也有接近150行,所以在这里就不贴这些代码,想了解的可以直接对着自己moc出来的cpp查看一下就好,我就直接对着这个宏声明讲了,moc文件中主要是重载了上述宏声明中那四个函数metaObject(), qt_metacast(), qt_metacall(), qt_static_metacall()。(其实信号函数的实现也是放在了moc里面,参见后面博文,本次不讲)

  • metaObject()

    metaObject()这个函数主要是用来得到一个元对象:实现一般如下:

const QMetaObject *cmdtimerthread::metaObject() const
{
    return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}

    道理很简单,返回一个MetaObject对象,如果当前没有就返回staticMetaObject这个静态对象,也是在moc中进行的定义:

const QMetaObject cmdtimerthread::staticMetaObject = { 
{ &QObject::staticMetaObject, qt_meta_stringdata_cmdtimerthread.data,qt_meta_data_cmdtimerthread, qt_static_metacall, Q_NULLPTR, Q_NULLPTR}
};

    各人由于类名和信号槽的差别会有命名上的差别,但是这个对象和metaObject的实现应该是大同小异的。

  • qt_metacast()

    此方法提供了一个metaObject到void 的转换,源码中引用的地方也几乎没有,因为void *还是比QMetaObject*强一点,到时候模块之间衔接的时候cast一下就好,估计我们当我们自己用到元对象系统的时候,自己调用这个qt_metacast转换成void ,在接收模块中,用cast转换成QMetaObject*这样如此如此。

  • qt_metacall()&qt_static_metacall()

    这两个方法放在一起说的原因就是他们有调用关系,而且很紧密,是信号槽对应最后的调用实现函数。主要分析qt_static_metacall(),因为qt_metacall()是调用的qt_static_metacall(this, _c, _id, _a);最后的槽调用过程在qt_static_metacall,这是一个静态方法,至于为什么选择用的静态方法,我想有可能是为了实现跨线程的信号槽调用。这其中还有SLOT,SIGNAL宏的实现方式也和这里有一点关系,这里就不再细说了。接下来我会细讲一下其他几个类在Qt元对象系统中的作用还有信号的相关内容。

猜你喜欢

转载自blog.csdn.net/moke_8453/article/details/54172878