Inside QT Series (九):QMetaObject class data members

我们来看一下QMetaObject的定义,我们先看一下QMetaObject对象中包含的成员数据。

  1. struct Q_CORE_EXPORT QMetaObject
  2. {
  3.     // ......
  4.     struct { // private data
  5.         const QMetaObject *superdata;
  6.         const char *stringdata;
  7.         const uint *data;
  8.         const void *extradata;
  9.     } d;
  10. };

上面的代码就是QMetaObject类所定义的全部数据成员。就是这些成员记录了所有signal,slot,property,class information这么多的信息。下面让我们来逐一解释这些成员变量:

const QMetaObject *superdata
这个变量指向与之对应的QObject类的父类,或者是祖先类的QMetaObject对象。

如何理解这一句话呢?我们知道,每一个QMetaObject对象,一定有一个与之相对应的QObject类(或者由其直接或间接派生出的子类),注意:这里是类,不是对象。

那么每一个QObject类(或其派生类)可能有一个父类,或者父类的父类,或者很多的继承层次之前的祖先类。或者没有父类(QObject)。那么 superdata 这个变量就是指向与其最接近的祖先类中的QMetaObject对象。对于QObject类QMetaObject对象来说,这是一个NULL指针,因为 QObject没有父类。

下面,让我们来举例说明:

  1. class Animal : public QObject
  2. {
  3.     Q_OBJECT
  4.     //.............
  5. };
  6. class Cat : public Animal
  7. {
  8.     Q_OBJECT
  9.     //.............
  10. }

那么,Cat::staticMetaObject.d.superdata 这个指针变量指向的对象是 Animal::staticMetaObject
而Animal::staticMetaObject.d.superdata 这个指针变量指向的对象是 QObject::staticMetaObject.
而 QObject::staticMetaObject.d.superdat 这个指针变量的值为 NULL。


但如果我们把上面class的定义修改为下面的定义,就不一样了:

  1. class Animal : public QObject
  2. {
  3.     // Q_OBJECT,这个 class 不定义这个
  4.     //.............
  5. };
  6. class Cat : public Animal
  7. {
  8.     Q_OBJECT
  9.     //.............
  10. }

那么,Cat::staticMetaObject.d.superdata 这个指针变量指向的对象是 QObject::staticMetaObject
因为 Animal::staticMetaObject 这个对象是不存在的。


const char *stringdata:

顾名思义,这是一个指向string data的指针。但它和我们平时所使用的一般的字符串指针却很不一样,我们平时使用的字符串指针只是指向一个字符串的指针,而这个指针却指向的是很多个字 符串。那么它不就是字符串数组吗?哈哈,也不是。因为C++的字符串数组要求数组中的每一个字符串拥有相同的长度,这样才能组成一个数组。那它是不是一个 字符串指针数组呢?也不是,那它到底是什么呢?让我们来看一看它的具体值,还是让我们以QObject这个class的QMetaObject为例来说明 吧。

下面是QObject::staticMetaObject.d.stringdata指针所指向的多个字符串数组,其实它就是指向一个连续的内存区,而这个连续的内存区中保存了若干个字符串。

  1. static const char qt_meta_stringdata_QObject[] =
  2. {
  3.     "QObject/0/0destroyed(QObject*)/0destroyed()/0"
  4.     "deleteLater()/0_q_reregisterTimers(void*)/0"
  5.     "QString/0objectName/0parent/0QObject(QObject*)/0"
  6.     "QObject()/0"
  7. };

这个字符串都是些什么内容呀?有,Class Name, Signal Name, Slot Name, Property Name。看到这些大家是不是觉得很熟悉呀,对啦,他们就是Meta System所支持的最核心的功能属性了。

既然他们都是不等长的字符串,那么Qt是如何来索引这些字符串,以便于在需要的时候能正确的找到他们呢?第三个成员正式登场了。

 

const uint *data;

这个指针本质上就是指向一个正整数数组,只不过在不同的object中数组的长度都不尽相同,这取决于与之相对应的class中定义了多少signal,slot,property。

这个整数数组的的值,有一部分指出了前一个变量(stringdata)中不同字符串的索引值,但是这里有一点需要注意的是,这里面的数值并不是直接标明了每一个字符串的索引值,这个数值还需要通过一个相应的算法计算之后,才能获得正确的字符串的索引值。

下面是QObject::staticMetaObject.d.data指针所指向的正整数数组的值。

  1. static const uint qt_meta_data_QObject[] =
  2. {
  3. // content:
  4.        2,       // revision
  5.        0,       // classname
  6.        0,    0, // classinfo
  7.        4,   12, // methods
  8.        1,   32, // properties
  9.        0,    0, // enums/sets
  10.        2,   35, // constructors
  11. // signals: signature, parameters, type, tag, flags
  12.        9,    8,    8,    8, 0x05,
  13.       29,    8,    8,    8, 0x25,
  14. // slots: signature, parameters, type, tag, flags
  15.       41,    8,    8,    8, 0x0a,
  16.       55,    8,    8,    8, 0x08,
  17. // properties: name, type, flags
  18.       90,   82, 0x0a095103,
  19. // constructors: signature, parameters, type, tag, flags
  20.      108,  101,    8,    8, 0x0e,
  21.      126,    8,    8,    8, 0x2e,
  22.        0        // eod
  23. };

简单的说明一下,

第一个section,就是 //content 区域的整数值,这一块区域在每一个QMetaObject的实体对象中数量都是相同的,含义也相同,但具体的值就不同了。专门有一个struct定义了这个section,其含义在上面的注释中已经说的很清楚了。

  1. struct QMetaObjectPrivate
  2. {
  3.     int revision;
  4.     int className;
  5.     int classInfoCount, classInfoData;
  6.     int methodCount, methodData;
  7.     int propertyCount, propertyData;
  8.     int enumeratorCount, enumeratorData;
  9.     int constructorCount, constructorData;
  10. };

这个 struct 就是定义第一个secton的,和上面的数值对照一下,很清晰,是吧?

第二个section,以 // signals 开头的这段。这个section中的数值指明了QObject这个class包含了两个signal,

第三个section,以 // slots 开头的这段。这个section中的数值指明了QObject这个class包含了两个slot。

第四个section,以 // properties 开头的这段。这个section中的数值指明了QObject这个class包含有一个属性定义。

第五个section,以 // constructors 开头的这段,指明了QObject这个class有两个constructor。

const void *extradata;

这是一个指向QMetaObjectExtraData数据结构的指针,关于这个指针,这里先略过。

对于每一个具体的整数值与其所指向的实体数据之间的对应算法,实在是有点儿麻烦,这里就不讲解细节了,有兴趣的朋友自己去读一下源代码,一定会有很多发现。

 

 

====================================
声明:
《Inside Qt Series》专栏文章是Qt核心技术论坛(InsideQt.com)原创技术文章。
本系列专栏文章可随意转载,但必须保留本段声明和每一篇文章的原始地址。
未经作者同意,不得用于商业用途
《Inside Qt Series》专栏文章总索引:
http://www.insideqt.com/bbs/viewthread.php?tid=9
本文原始地址:
http://www.insideqt.com/bbs/viewthread.php?tid=23
====================================

前一篇:Meta Object Class overview
http://www.insideqt.com/bbs/viewthread.php?tid=17
后一篇:connect,幕后的故事
http://www.insideqt.com/bbs/viewthread.php?tid=37
====================================

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值