Qt的元对象(Meta-Object)系统简介(转)
Qt的元對象系統基于如下三件事情:
?
1.類:QObject,為所有需要利用原對象系統的對象提供了一個基類。
2.宏:Q_OBJECT,通??梢月暶髟陬惖乃接卸沃?#xff0c;讓該類可以使用元對象的特性,比如動態屬性,信號和槽。
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,說明對象類型不兼容。
當某一個Object emit一個signal的時候,它就是一個sender,系統會記錄下當前是誰emit出這個signal的,所以你在對應的slot里就可以通過sender()得到當前是誰invoke了你的slot,對應的是QObject->d->sender。
????有可能多個Object的signal會連接到同一個signal(例如多個Button可能會connect到一個slot函數onClick()),因此這是就需要判斷到底是哪個Object emit了這個signal,根據sender的不同來進行不同的處理。這時就要用到qobject_cast()。
?
例如,假設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宏,不管你實際上是否使用信號和槽,以及屬性。
?
例子:
connect(pushButton_2,SIGNAL(clicked()),this,SLOT(on_pushButton_clicked()));?
connect(pushButton,SIGNAL(clicked()),this,SLOT(on_pushButton_clicked()));
void MainWindow::on_pushButton_clicked()?
{
? QPushButton*pt=qobject_cast <QPushButton*>(sender());
if(!pt)
return;?
? QString str;
if (pt = = pushButton)?
????????str="1";
else??if (pt = = pushButton_2)?
? ???????str="2";?
? }?
轉載于:https://www.cnblogs.com/qq78292959/archive/2012/08/20/2648099.html
總結
以上是生活随笔為你收集整理的Qt的元对象(Meta-Object)系统简介(转)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 暴雨把网友新买的华为Tag防丢精灵淋透
- 下一篇: 在64位系统上注册并使用32位的COM组