Inside Qt Series (九):QMetaObject class data members

來源:互聯網
上載者:User

我們來看一下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)原創技術文章。
本系列專欄文章可隨意轉載,但必須保留本段聲明和每一篇文章的原始地址。
作者保留著作權,未經作者同意,不得用於任何商業用途

《Inside Qt Series》專欄文章總索引: http://www.qkevin.com/qt
本文原始地址:http://www.qkevin.com/archives/81

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.