Qt的元对象(Meta-Object)系统简介(转)
Qt的元對(duì)象系統(tǒng)基于如下三件事情:
?
1.類:QObject,為所有需要利用原對(duì)象系統(tǒng)的對(duì)象提供了一個(gè)基類。
2.宏:Q_OBJECT,通常可以聲明在類的私有段中,讓該類可以使用元對(duì)象的特性,比如動(dòng)態(tài)屬性,信號(hào)和槽。
3.編譯器:元對(duì)象編譯器(moc)為每個(gè)QObject子對(duì)象自動(dòng)生成必要的代碼來(lái)實(shí)現(xiàn)元對(duì)象特性。
moc工具會(huì)讀入C++的源文件,如果它發(fā)現(xiàn)了一個(gè)或者多個(gè)聲明了Q_OBJECT宏的類,它就創(chuàng)建另一個(gè)C++源文件,為每個(gè)類生成包含元對(duì)象實(shí)現(xiàn)的代碼。這些編譯生成的源文件通常都已經(jīng)被包含到類的源文件中或者和類的實(shí)現(xiàn)同時(shí)被編譯和鏈接。
?
除了為對(duì)象間的通信提供信號(hào)和槽(signals and slots)機(jī)制之外,元對(duì)象的代碼還提供下列特性:
·QObject::metaObject()返回與該類綁定的meta-object對(duì)象。
·QMetaObject::className()可以在運(yùn)行時(shí)以字符串的形式返回類的名字,不需要C++編譯器原生的運(yùn)行時(shí)類型信息(RTTI)的支持。
·QObject::inherits()函數(shù)返回繼承信息:對(duì)象是否是QObject繼承樹上一個(gè)類的實(shí)例。
·QObject::tr()和QObject::trUtf8()提供國(guó)際化支持,將字符串翻譯成指定的語(yǔ)言。
·QObject::setProperty()和QObject::property()通過(guò)名字動(dòng)態(tài)設(shè)置和獲取對(duì)象屬性。
·QMetaObject::newInstance()構(gòu)造該類的一個(gè)新實(shí)例。
除此之外你還可以用qobject_cast()動(dòng)態(tài)轉(zhuǎn)換QObject類的類型。qobject_cast()函數(shù)和標(biāo)準(zhǔn)C++的dynamic_cast()功能類似,只是其不需要RTTI的支持,而且可以跨越動(dòng)態(tài)連接庫(kù)的邊界。它嘗試將它的參數(shù)cast成尖括號(hào)內(nèi)的對(duì)象類型,如果對(duì)象是正確的類型(運(yùn)行時(shí)決定)則返回非零,否則返回0,說(shuō)明對(duì)象類型不兼容。
當(dāng)某一個(gè)Object emit一個(gè)signal的時(shí)候,它就是一個(gè)sender,系統(tǒng)會(huì)記錄下當(dāng)前是誰(shuí)emit出這個(gè)signal的,所以你在對(duì)應(yīng)的slot里就可以通過(guò)sender()得到當(dāng)前是誰(shuí)invoke了你的slot,對(duì)應(yīng)的是QObject->d->sender。
????有可能多個(gè)Object的signal會(huì)連接到同一個(gè)signal(例如多個(gè)Button可能會(huì)connect到一個(gè)slot函數(shù)onClick()),因此這是就需要判斷到底是哪個(gè)Object emit了這個(gè)signal,根據(jù)sender的不同來(lái)進(jìn)行不同的處理。這時(shí)就要用到qobject_cast()。
?
例如,假設(shè)MyWidget繼承自QWidget,同時(shí)也聲明了Q_OBJECT宏,
??????????QObject *obj = new MyWidget;
QObject類型的變量obj實(shí)際上指向一個(gè)MyWidget對(duì)象,因此我們可以這樣進(jìn)行類型轉(zhuǎn)換:
??????????QWidget *widget = qobject_cast<QWidget *>(obj);
到MyWidget的轉(zhuǎn)型可以成功是因?yàn)閝object_cast()并沒(méi)有對(duì)Qt內(nèi)建對(duì)象和定制的擴(kuò)展對(duì)象分別對(duì)待。
??????????QLabel *label = qobject_cast<QLabel *>(obj);?????// label is 0
另一方面到QLabel的轉(zhuǎn)型則會(huì)失敗,指針會(huì)被設(shè)置為0。這樣使得我們可以在運(yùn)行時(shí)根據(jù)對(duì)象類型,對(duì)不同類型的對(duì)象進(jìn)行不同的處理:
???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宏和原對(duì)象信息的情況下仍舊使用QObject作為基類,但是像信號(hào)和槽以及其他這里描述的特性將無(wú)法使用。從元對(duì)象系統(tǒng)的觀點(diǎn)來(lái)看,一個(gè)沒(méi)有元對(duì)象代碼的QObject子類和其最接近的有元對(duì)象代碼的祖先是等同的。這也就意味著,QMetaObject::className()將不會(huì)返回你的類的真實(shí)的名字,而是該類某一個(gè)祖先的名字。
因此,我們強(qiáng)烈建議所QObject的子類都是用Q_OBJECT宏,不管你實(shí)際上是否使用信號(hào)和槽,以及屬性。
?
例子:
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";?
? }?
轉(zhuǎn)載于:https://www.cnblogs.com/qq78292959/archive/2012/08/20/2648099.html
總結(jié)
以上是生活随笔為你收集整理的Qt的元对象(Meta-Object)系统简介(转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 暴雨把网友新买的华为Tag防丢精灵淋透
- 下一篇: 京东方AMOLED屏幕暴跌32.7%:期