Inside Qt Series (九):QMetaObject class data members

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

struct Q_CORE_EXPORT QMetaObject
{
    // ……
    struct { // private data
        const QMetaObject *superdata;
        const char *stringdata;
        const uint *data;
        const void *extradata;
    } d;
};

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

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

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

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

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

class Animal : public QObject
{
    Q_OBJECT
    //………….
};

class Cat : public Animal
{
    Q_OBJECT
    //………….
}

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

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

class Animal : public QObject
{
    // Q_OBJECT,这个 class 不定义这个
    //………….
};

class Cat : public Animal
{
    Q_OBJECT
    //………….
}

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

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

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

static const char qt_meta_stringdata_QObject[] =
{
    "QObject/0/0destroyed(QObject*)/0destroyed()/0"
    "deleteLater()/0_q_reregisterTimers(void*)/0"
    "QString/0objectName/0parent/0QObject(QObject*)/0"
    "QObject()/0"
};

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

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

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

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

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

static const uint qt_meta_data_QObject[] =
{
// content:
       2,       // revision
       0,       // classname
       0,    0, // classinfo
       4,   12, // methods
       1,   32, // properties
       0,    0, // enums/sets
       2,   35, // constructors

// signals: signature, parameters, type, tag, flags
       9,    8,    8,    8, 0×05,
      29,    8,    8,    8, 0×25,

// slots: signature, parameters, type, tag, flags
      41,    8,    8,    8, 0×0a,
      55,    8,    8,    8, 0×08,

// properties: name, type, flags
      90,   82, 0×0a095103,

// constructors: signature, parameters, type, tag, flags
     108,  101,    8,    8, 0×0e,
     126,    8,    8,    8, 0×2e,

       0        // eod
};

简单的说明一下,

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

struct QMetaObjectPrivate
{
    int revision;
    int className;
    int classInfoCount, classInfoData;
    int methodCount, methodData;
    int propertyCount, propertyData;
    int enumeratorCount, enumeratorData;
    int constructorCount, constructorData;
};

这个 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》专栏文章是(http://www.qkevin.com)原创技术文章。
本系列专栏文章可随意转载,但必须保留本段声明和每一篇文章的原始地址。
作者保留版权,未经作者同意,不得用于任何商业用途

你可能感兴趣的:(properties,struct,Class,Parameters,qt,Signal)