RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Qt“靈魂”之Meta-Object系統(tǒng)

嵌入式小生 ? 來源:嵌入式小生 ? 2023-02-10 13:50 ? 次閱讀

一、Meta-Object簡(jiǎn)介

Meta-Object即是Qt的元對(duì)象系統(tǒng),下文都以元對(duì)象系統(tǒng)進(jìn)行描述。在Qt中,具有標(biāo)志性特征的則是信號(hào)和槽函數(shù)機(jī)制,該機(jī)制的背后實(shí)現(xiàn)本質(zhì)上則是元對(duì)象系統(tǒng)。編寫Qt代碼的時(shí)候,在定義類的時(shí)候,需要放置一個(gè)Q_OBJECT,為什么呢?后文會(huì)描述到,例如如下代碼:

f8b5a762-a8dc-11ed-bfe3-dac502259ad0.pngimage-20230207220020441

Q_OBJECT本質(zhì)上是一個(gè)宏定義,在進(jìn)行Qt開發(fā)時(shí),所有QObject的派生類都推薦在頭文件中放置Q_OBJECT宏定義,該宏定義如下(出自qobjectdefs.h文件):

#defineQ_OBJECT
public:
QT_WARNING_PUSH
Q_OBJECT_NO_OVERRIDE_WARNING
staticconstQMetaObjectstaticMetaObject;
virtualconstQMetaObject*metaObject()const;
virtualvoid*qt_metacast(constchar*);
virtualintqt_metacall(QMetaObject::Call,int,void**);
QT_TR_FUNCTIONS
private:
Q_OBJECT_NO_ATTRIBUTES_WARNING
Q_DECL_HIDDEN_STATIC_METACALLstaticvoidqt_static_metacall(QObject*,QMetaObject::Call,int,void**);
QT_WARNING_POP
structQPrivateSignal{};
QT_ANNOTATE_CLASS(qt_qobject,"")

Qt中,元對(duì)象系統(tǒng)包含了支持元對(duì)象系統(tǒng)的程序,宏定義,基類,接口函數(shù)。這些東西共同構(gòu)成了Qt的元對(duì)象系統(tǒng):

(1)QObject為想要使用元對(duì)象系統(tǒng)的對(duì)象提供了基類。

(2)Q_OBJECT宏用于啟動(dòng)元對(duì)象特性,例如:動(dòng)態(tài)屬性、信號(hào)和槽函數(shù)機(jī)制等。

(3)元對(duì)象編譯器(moc)為每個(gè)QObject子類生成實(shí)現(xiàn)元對(duì)象特性所需要的代碼。

在實(shí)際Qt程序設(shè)計(jì)中,在派生自QObject的類定義中加上Q_OBJECT后,則可以使用元對(duì)象系統(tǒng)所支持的特性了。

二、元對(duì)象系統(tǒng)背后機(jī)制

如果在派生自QObject的類定義中加上了Q_OBJECT后,在編譯構(gòu)建過程中,元對(duì)象系統(tǒng)的moc工具(本文以Windows平臺(tái)為例,該工具則位于具體Qt版本目錄下的bin目錄中)

f8cd9250-a8dc-11ed-bfe3-dac502259ad0.png

在Windows命令行下運(yùn)行,可獲知如下信息

f8f59df4-a8dc-11ed-bfe3-dac502259ad0.png

在QtCreator集成開發(fā)環(huán)境中,當(dāng)點(diǎn)擊構(gòu)建按鈕后,QtCreator會(huì)自動(dòng)調(diào)用moc工具,該工具會(huì)讀取一個(gè)C++源文件,如果它發(fā)現(xiàn)一個(gè)或多個(gè)包含Q_OBJECT宏的類聲明,那么則會(huì)生成另外一個(gè)C++源文件,源文件中包含每個(gè)類的元對(duì)象代碼。接著,生成的源文件要么被#include包含到類的源文件中,要么被編譯并鏈接到類的實(shí)現(xiàn)中。例如下列一個(gè)簡(jiǎn)單的項(xiàng)目工程,源碼結(jié)構(gòu)如下:

f91d39cc-a8dc-11ed-bfe3-dac502259ad0.png

從上圖可知,工程中包含了一個(gè)main.cpp、一個(gè)主窗口描述文件mainwindow.cpp/.h、一個(gè)stylesheeteditor.cpp/.h文件,由于mainwindow.cpp/.h、stylesheeteditor.cpp/.h支持Qt的元對(duì)象系統(tǒng),在編譯構(gòu)建過程中,則會(huì)生成支持元對(duì)象系統(tǒng)的中間文件,如下圖所示:

f9334500-a8dc-11ed-bfe3-dac502259ad0.png

從上圖可知,這些文件都以moc_xxx方式進(jìn)行命名,最后結(jié)合其他的文件生成了程序可執(zhí)行體(stylesheet.exe),整個(gè)過程可如下圖所示(Windows平臺(tái)):

f93fbf6a-a8dc-11ed-bfe3-dac502259ad0.png

三、再談元對(duì)象系統(tǒng)

除了提供對(duì)象之間通信的信號(hào)和槽函數(shù)機(jī)制(這是引入該系統(tǒng)的主要原因),元對(duì)象系統(tǒng)還提供以下的功能:

(1)Object::metaObject():返回類的關(guān)聯(lián)元對(duì)象。

(2)QMetaObject::className():在運(yùn)行時(shí)以字符串的形式返回類名,而不需要通過C++編譯器提供本地運(yùn)行時(shí)類型信息(RTTI)支持。

(3)QObject::inherits():函數(shù)返回一個(gè)對(duì)象是否是在QObject繼承樹中繼承指定類實(shí)例。

(4)QObject::tr()和QObject::trUtf8()為國(guó)際化翻譯字符串。

(5)QObject::setProperty()和QObject::property()根據(jù)名稱動(dòng)態(tài)設(shè)置和獲取屬性。

(6)QMetaObject::newInstance():構(gòu)造類的新實(shí)例。

除了上述所列的功能,還可以使用qobject_cast()對(duì)QObject類執(zhí)行動(dòng)態(tài)強(qiáng)制類型轉(zhuǎn)換,qobject_cast()函數(shù)的行為類似于標(biāo)準(zhǔn)C++ 的dynamic_cast(),它的優(yōu)點(diǎn)是不需要RTTI支持,并且可以跨動(dòng)態(tài)庫工作。該函數(shù)嘗試將其參數(shù)轉(zhuǎn)換為尖括號(hào)中指定的指針類型,如果對(duì)象的類型正確(在運(yùn)行時(shí)確定),則返回非零指針;如果對(duì)象的類型不兼容,則返回nullptr。

例如,假設(shè)有一個(gè)MyWidget繼承自QWidget,并使用了Q_OBJECT宏聲明,然后使用new創(chuàng)建該實(shí)例:

QObject*obj=newMyWidget;

類型為QObject *的obj變量實(shí)際上引用了一個(gè)MyWidget對(duì)象,所以我們可以對(duì)它進(jìn)行適當(dāng)?shù)念愋娃D(zhuǎn)換,如下代碼:

QWidget*widget=qobject_cast(obj);

從QObject到QWidget的轉(zhuǎn)換是成功的,因?yàn)樵搶?duì)象實(shí)際上是一個(gè)MyWidget,它是QWidget的一個(gè)子類。既然知道obj是一個(gè)MyWidget,我們也可以將它c(diǎn)ast到MyWidget *,如下代碼:

MyWidget*myWidget=qobject_cast(obj);

上述代碼對(duì)MyWidget的轉(zhuǎn)換是也成功的,因?yàn)閝object_cast()在內(nèi)置Qt類型和自定義類型之間沒有區(qū)別。

然而對(duì)于下列代碼:

QLabel*label=qobject_cast(obj);

對(duì)QLabel的強(qiáng)制轉(zhuǎn)換將失敗,會(huì)將指針設(shè)置為0。因此可以在運(yùn)行時(shí)處理不同類型的對(duì)象,例如:

if(QLabel*label=qobject_cast(obj))
{
label->setText(tr("iriczhao"));
}
elseif(QPushButton*button=qobject_cast(obj))
{
button->setText(tr("嵌入式小生"));
}

上述代碼使用qobject_case()對(duì)obj進(jìn)行了向QLabel和QPushButton的強(qiáng)制轉(zhuǎn)換,如果轉(zhuǎn)換成功,則設(shè)置對(duì)應(yīng)的顯示文本。

四、小生總結(jié)

在實(shí)際Qt開發(fā)過程中,雖然可以在沒有Q_OBJECT宏和元對(duì)象代碼的情況下將QObject作為基類,但如果沒有使用Q_OBJECT宏,則信號(hào)和槽函數(shù)機(jī)制或在本文中描述的其他特性都不能使用。從元對(duì)象系統(tǒng)的角度來看,一個(gè)沒有元代碼的QObject子類等價(jià)于它最近的有元對(duì)象代碼的祖先。這意味著,例如,QMetaObject::className()將不會(huì)返回自己類的實(shí)際名稱,而是這個(gè)祖先的類名稱。

因此,在實(shí)際Qt開發(fā)過程中,無論實(shí)際上是否使用了信號(hào)和槽函數(shù)機(jī)制,都強(qiáng)烈建議QObject的所有子類都使用Q_OBJECT宏。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4327

    瀏覽量

    62569
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4779

    瀏覽量

    68521
  • Meta
    +關(guān)注

    關(guān)注

    0

    文章

    270

    瀏覽量

    11378
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1623

    瀏覽量

    49108
  • Qt
    Qt
    +關(guān)注

    關(guān)注

    1

    文章

    302

    瀏覽量

    37899

原文標(biāo)題:Qt“靈魂”之Meta-Object系統(tǒng)

文章出處:【微信號(hào):嵌入式小生,微信公眾號(hào):嵌入式小生】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    【AWorks試用體驗(yàn)】學(xué)習(xí)筆記(3)一個(gè)關(guān)于 Qt 的 demo

    器。Qt是面向?qū)ο蟮目蚣?,使用特殊的代碼生成擴(kuò)展(稱為元對(duì)象編譯器(Meta Object Compiler, moc))以及一些宏,易于擴(kuò)展,允許組件編程。2008年,奇趣科技被諾基亞公司收購,
    發(fā)表于 09-03 19:51

    qt creator編譯QT5應(yīng)用

    +xfsl-imx-fb-glibc-x86_64-meta-toolchain-qt
    發(fā)表于 05-05 15:17

    如何對(duì)meta-toolchain-qt5進(jìn)行bitbake?

    大家好,我設(shè)法在我的 STM32MP157C-DK2 上構(gòu)建了具有一些額外圖像功能的 st-example-image-qt?,F(xiàn)在我只想運(yùn)行 bitbake meta-toolchain-qt5 但構(gòu)建最終會(huì)出現(xiàn)我無法解決的錯(cuò)誤。當(dāng)我嘗試構(gòu)建它時(shí),我附上了輸出控制臺(tái)。你知
    發(fā)表于 02-07 10:14

    Qt 跨平臺(tái)C++圖形用戶界面應(yīng)用程序開發(fā)框架

    的代碼生成擴(kuò)展(稱為元對(duì)象編譯器(Meta Object Compiler, moc))以及一些宏,Qt很容易擴(kuò)展,并且允許真正地組件編程。
    發(fā)表于 03-28 21:03

    Yocto添加meta-webkit層時(shí)出現(xiàn)do_compile錯(cuò)誤怎么解決?

    大家好,我正在研究 VAR-SOM IMX8,我正在構(gòu)建 Qt5 圖像,yocto 版本是dunfell-fslc-5.4-2.1.x-mx8-v1.5。當(dāng)我嘗試將 meta-webkit 層添加到
    發(fā)表于 03-30 07:45

    【米爾MYD-JX8MMA7開發(fā)板-ARM+FPGA架構(gòu)試用體驗(yàn)】十一、QT-HMI V2.0系統(tǒng)

    代碼進(jìn)行方便的交互,使用起來非常方便。QMl是一種高效的開發(fā)UI 的語言。QML(Qt Meta-Object Language,Qt元對(duì)象語言)是一種聲明式編程語言,并且它是Qt框架
    發(fā)表于 05-23 09:34

    bitbake imx-image-full時(shí)出現(xiàn)qt6錯(cuò)誤怎么解決?

    /imx-yocto-bsp/sources/meta-qt6/recipes-qt/qt6/qtbase_git.bb: do_compile) 失敗,退出代碼為“1” 有什么辦法可以解決這個(gè)問題嗎?謝謝
    發(fā)表于 05-29 08:11

    Java Object Serialization Spec

    Java Object Serialization SpecificationObject serialization in the Java™system is the process
    發(fā)表于 10-14 17:39 ?7次下載

    什么是CORBA (Common Object Reques

    什么是CORBA (Common Object Request Broker Architecture)  英文縮寫: CORBA (Common Object Request Broker Architecture) 中文譯名: 通用對(duì)象請(qǐng)求
    發(fā)表于 02-22 11:48 ?957次閱讀

    qt4圖形設(shè)計(jì)與嵌入式開發(fā)

    生成擴(kuò)展(稱為元對(duì)象編譯器(meta object Compiler moc))以及一些宏,易于擴(kuò)展,允許組件編程。
    發(fā)表于 11-18 16:59 ?10次下載

    Qt圖形編程基礎(chǔ)使用Qt編寫“Hello,World”程序?qū)嶒?yàn)

    分享到:標(biāo)簽:Qt圖形編程 Linux 操作系統(tǒng) 12.3 實(shí)驗(yàn)內(nèi)容使用Qt編寫Hello,World程序 1.實(shí)驗(yàn)?zāi)康?通過編寫一個(gè)跳動(dòng)的Hello,World字符串,進(jìn)一步熟悉嵌入式Qt
    發(fā)表于 10-18 14:44 ?1次下載
    <b class='flag-5'>Qt</b>圖形編程基礎(chǔ)<b class='flag-5'>之</b>使用<b class='flag-5'>Qt</b>編寫“Hello,World”程序?qū)嶒?yàn)

    嵌入式linux應(yīng)用開發(fā)QT

    隨著linux系統(tǒng)及基于linux系統(tǒng)的嵌入式產(chǎn)品的蓬勃發(fā)展,Qt、Qt/Embedded、Qtopia的字樣越來頻繁的出現(xiàn)在我們面前。 QT
    發(fā)表于 11-06 14:05 ?4次下載

    Embeded linuxQt gdb

    Embeded linuxQt gdb
    發(fā)表于 05-15 13:52 ?1318次閱讀
    Embeded linux<b class='flag-5'>之</b><b class='flag-5'>Qt</b> gdb

    Windows下的QT系統(tǒng)開發(fā)環(huán)境搭建

    生成擴(kuò)展(稱為元對(duì)象編譯器(Meta Object Compiler, moc))以及一些宏,Qt很容易擴(kuò)展,并且允許真正地組件編程。
    的頭像 發(fā)表于 05-17 11:39 ?3659次閱讀
    Windows下的<b class='flag-5'>QT</b><b class='flag-5'>系統(tǒng)</b>開發(fā)環(huán)境搭建

    Object類中的所有方法

    Object 類屬于 java.lang 包,此包下的所有類在使用時(shí)無需手動(dòng)導(dǎo)入,系統(tǒng)會(huì)在程序編譯期間自動(dòng)導(dǎo)入。Object 類是所有類的基類,當(dāng)一個(gè)類沒有直接繼承某個(gè)類時(shí),默認(rèn)繼承Objec
    的頭像 發(fā)表于 10-13 11:50 ?523次閱讀
    <b class='flag-5'>Object</b>類中的所有方法
    RM新时代网站-首页