元對象系統

系統介紹
Qt 元對象系統(Meta-Object System)
Qt的元對象系統基於如下三件事情:
1. 類:QObject,為所有需要利用元對象系統的對象提供了一個基類。
2. 宏:Q_OBJECT,通常可以聲明在類的私有段中,讓該類可以使用元對象的特性,比如動態屬性,信號和槽。
3. 編譯器:元對象編譯器(moc)為每個QObject子對象自動生成必要的代碼來實現元對象特性。
moc工具會讀入C++的源檔案,如果它發現了一個或者多個聲明了Q_OBJECT宏的類,它就創建另一個C++源檔案,為每個類生成包含元對象實現的代碼。這些編譯生成的源檔案通常都已經被包含到類的源檔案中或者和類的實現同時被編譯和連結。
除了為對象間的通信提供信號和槽(signals and slots)機制之外,元對象的代碼還提供下列特性:
· QObject::metaObject()返回與該類綁定的meta-object對象。
· QMetaObject::className()可以在運行時以字元串的形式返回類的名字,不需要C++編譯器原生的運行時類型信息(RTTI)的支持。
· QObject::inherits()函式返回繼承信息:對象是否是QObject繼承樹上一個類的實例。
· QObject::tr()和QObject::trUtf8()提供國際化支持,將字元串翻譯成指定的語言。
· QObject::setProperty()和QObject::property()通過名字動態設定和獲取對象屬性。
· QMetaObject::newInstance()構造該類的一個新實例。
除此之外你還可以用qobject_cast()動態轉換QObject類的類型。qobject_cast()函式和標準C++的dynamic_cast()功能類似,只是其不需要RTTI的支持,而且可以跨越動態連線庫的邊界。它嘗試將它的參數cast成尖括弧內的對象類型,如果對象是正確的類型(運行時決定)則返回非零,否則返回0,說明對象類型不兼容。
例如,假設MyWidget繼承自QWidget,同時也聲明了Q_OBJECT宏,
QObject *obj = new MyWidget;QObject類型的變數obj實際上指向一個MyWidget對象,因此我們可以這樣進行類型轉換:
QWidget *widget = qobject_cast<QWidget *>(obj);到MyWidget的轉型可以成功是因為qobject_cast()並沒有對Qt內建對象和定製的擴展對象分別對待。
QLabel *label = qobject_cast<QLabel *>(obj); // label is 0另一方面到QLabel的轉型則會失敗,指針會被設定為0。這樣使得我們可以在運行時根據對象類型,對不同類型的對象進行不同的處理:
if (QLabel *label = qobject_cast<QLabel *>(obj)) { label->setText(tr("Ping")); } else if (QPushButton *button = qobject_cast<QPushButton *>(obj)) { button->setText(tr("Pong!")); }儘管我們可以在不用Q_OBJECT宏和原對象信息的情況下仍舊使用QObject作為基類,但是像信號和槽以及其他這裡描述的特性將無法使用。從元對象系統的觀點來看,一個沒有元對象代碼的QObject子類和其最接近的有元對象代碼的祖先是等同的。這也就意味著,QMetaObject::className()將不會返回你的類的真實的名字,而是該類某一個祖先的名字。
因此,我們強烈建議所有QObject的子類都是用Q_OBJECT宏,不管你實際上是否使用信號和槽,以及屬性

相關詞條

熱門詞條

聯絡我們