0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創(chuàng)作中心

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

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

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

嵌入式小生 ? 來(lái)源:嵌入式小生 ? 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)。編寫(xiě)Qt代碼的時(shí)候,在定義類的時(shí)候,需要放置一個(gè)Q_OBJECT,為什么呢?后文會(huì)描述到,例如如下代碼:

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

Q_OBJECT本質(zhì)上是一個(gè)宏定義,在進(jìn)行Qt開(kāi)發(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)建過(guò)程中,元對(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集成開(kāi)發(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)建過(guò)程中,則會(huì)生成支持元對(duì)象系統(tǒng)的中間文件,如下圖所示:

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

從上圖可知,這些文件都以moc_xxx方式進(jìn)行命名,最后結(jié)合其他的文件生成了程序可執(zhí)行體(stylesheet.exe),整個(gè)過(guò)程可如下圖所示(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í)以字符串的形式返回類名,而不需要通過(guò)C++編譯器提供本地運(yùn)行時(shí)類型信息(RTTI)支持。

(3)QObject::inherits():函數(shù)返回一個(gè)對(duì)象是否是在QObject繼承樹(shù)中繼承指定類實(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)庫(kù)工作。該函數(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類型和自定義類型之間沒(méi)有區(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開(kāi)發(fā)過(guò)程中,雖然可以在沒(méi)有Q_OBJECT宏和元對(duì)象代碼的情況下將QObject作為基類,但如果沒(méi)有使用Q_OBJECT宏,則信號(hào)和槽函數(shù)機(jī)制或在本文中描述的其他特性都不能使用。從元對(duì)象系統(tǒng)的角度來(lái)看,一個(gè)沒(méi)有元代碼的QObject子類等價(jià)于它最近的有元對(duì)象代碼的祖先。這意味著,例如,QMetaObject::className()將不會(huì)返回自己類的實(shí)際名稱,而是這個(gè)祖先的類名稱。

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

審核編輯:湯梓紅

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

    關(guān)注

    3

    文章

    4371

    瀏覽量

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

    關(guān)注

    30

    文章

    4889

    瀏覽量

    70287
  • Meta
    +關(guān)注

    關(guān)注

    0

    文章

    300

    瀏覽量

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

    關(guān)注

    1

    文章

    1656

    瀏覽量

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

    關(guān)注

    1

    文章

    313

    瀏覽量

    38818

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

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

收藏 0人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

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

    器。Qt是面向?qū)ο蟮目蚣?,使用特殊的代碼生成擴(kuò)展(稱為元對(duì)象編譯器(Meta Object Compiler, moc))以及一些宏,易于擴(kuò)展,允許組件編程。2008年,奇趣科技被諾基亞公司收購(gòu),
    發(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)我無(wú)法解決的錯(cuò)誤。當(dāng)我嘗試構(gòu)建它時(shí),我附上了輸出控制臺(tái)。你知
    發(fā)表于 02-07 10:14

    Qt 跨平臺(tái)C++圖形用戶界面應(yīng)用程序開(kāi)發(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開(kāi)發(fā)板-ARM+FPGA架構(gòu)試用體驗(yàn)】十一、QT-HMI V2.0系統(tǒng)

    代碼進(jìn)行方便的交互,使用起來(lái)非常方便。QMl是一種高效的開(kāi)發(fā)UI 的語(yǔ)言。QML(Qt Meta-Object Language,Qt元對(duì)象語(yǔ)言)是一種聲明式編程語(yǔ)言,并且它是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è)問(wèn)題嗎?謝謝
    發(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)  英文縮寫(xiě): CORBA (Common Object Request Broker Architecture) 中文譯名: 通用對(duì)象請(qǐng)求
    發(fā)表于 02-22 11:48 ?1092次閱讀

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

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

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

    分享到:標(biāo)簽:Qt圖形編程 Linux 操作系統(tǒng) 12.3 實(shí)驗(yàn)內(nèi)容使用Qt編寫(xiě)Hello,World程序 1.實(shí)驗(yàn)?zāi)康?通過(guò)編寫(xiě)一個(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>編寫(xiě)“Hello,World”程序?qū)嶒?yàn)

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

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

    Embeded linuxQt gdb

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

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

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

    Object類中的所有方法

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

    電子發(fā)燒友

    中國(guó)電子工程師最喜歡的網(wǎng)站

    • 2931785位工程師會(huì)員交流學(xué)習(xí)
    • 獲取您個(gè)性化的科技前沿技術(shù)信息
    • 參加活動(dòng)獲取豐厚的禮品