0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Qt“灵魂”之Meta-Object系统

嵌入式小生 来源:嵌入式小生 2023-02-10 13:50 次阅读

一、Meta-Object简介

Meta-Object即是Qt的元对象系统,下文都以元对象系统进行描述。在Qt中,具有标志性特征的则是信号和槽函数机制,该机制的背后实现本质上则是元对象系统。编写Qt代码的时候,在定义类的时候,需要放置一个Q_OBJECT,为什么呢?后文会描述到,例如如下代码:

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

Q_OBJECT本质上是一个宏定义,在进行Qt开发时,所有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中,元对象系统包含了支持元对象系统的程序,宏定义,基类,接口函数。这些东西共同构成了Qt的元对象系统:

(1)QObject为想要使用元对象系统的对象提供了基类。

(2)Q_OBJECT宏用于启动元对象特性,例如:动态属性、信号和槽函数机制等。

(3)元对象编译器(moc)为每个QObject子类生成实现元对象特性所需要的代码。

在实际Qt程序设计中,在派生自QObject的类定义中加上Q_OBJECT后,则可以使用元对象系统所支持的特性了。

二、元对象系统背后机制

如果在派生自QObject的类定义中加上了Q_OBJECT后,在编译构建过程中,元对象系统的moc工具(本文以Windows平台为例,该工具则位于具体Qt版本目录下的bin目录中)

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

在Windows命令行下运行,可获知如下信息

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

在QtCreator集成开发环境中,当点击构建按钮后,QtCreator会自动调用moc工具,该工具会读取一个C++源文件,如果它发现一个或多个包含Q_OBJECT宏的类声明,那么则会生成另外一个C++源文件,源文件中包含每个类的元对象代码。接着,生成的源文件要么被#include包含到类的源文件中,要么被编译并链接到类的实现中。例如下列一个简单的项目工程,源码结构如下:

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

从上图可知,工程中包含了一个main.cpp、一个主窗口描述文件mainwindow.cpp/.h、一个stylesheeteditor.cpp/.h文件,由于mainwindow.cpp/.h、stylesheeteditor.cpp/.h支持Qt的元对象系统,在编译构建过程中,则会生成支持元对象系统的中间文件,如下图所示:

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

从上图可知,这些文件都以moc_xxx方式进行命名,最后结合其他的文件生成了程序可执行体(stylesheet.exe),整个过程可如下图所示(Windows平台):

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

三、再谈元对象系统

除了提供对象之间通信的信号和槽函数机制(这是引入该系统的主要原因),元对象系统还提供以下的功能:

(1)Object::metaObject():返回类的关联元对象。

(2)QMetaObject::className():在运行时以字符串的形式返回类名,而不需要通过C++编译器提供本地运行时类型信息(RTTI)支持。

(3)QObject::inherits():函数返回一个对象是否是在QObject继承树中继承指定类实例。

(4)QObject::tr()和QObject::trUtf8()为国际化翻译字符串。

(5)QObject::setProperty()和QObject::property()根据名称动态设置和获取属性。

(6)QMetaObject::newInstance():构造类的新实例。

除了上述所列的功能,还可以使用qobject_cast()对QObject类执行动态强制类型转换,qobject_cast()函数的行为类似于标准C++ 的dynamic_cast(),它的优点是不需要RTTI支持,并且可以跨动态库工作。该函数尝试将其参数转换为尖括号中指定的指针类型,如果对象的类型正确(在运行时确定),则返回非零指针;如果对象的类型不兼容,则返回nullptr。

例如,假设有一个MyWidget继承自QWidget,并使用了Q_OBJECT宏声明,然后使用new创建该实例:

QObject*obj=newMyWidget;

类型为QObject *的obj变量实际上引用了一个MyWidget对象,所以我们可以对它进行适当的类型转换,如下代码:

QWidget*widget=qobject_cast(obj);

从QObject到QWidget的转换是成功的,因为该对象实际上是一个MyWidget,它是QWidget的一个子类。既然知道obj是一个MyWidget,我们也可以将它cast到MyWidget *,如下代码:

MyWidget*myWidget=qobject_cast(obj);

上述代码对MyWidget的转换是也成功的,因为qobject_cast()在内置Qt类型和自定义类型之间没有区别。

然而对于下列代码:

QLabel*label=qobject_cast(obj);

对QLabel的强制转换将失败,会将指针设置为0。因此可以在运行时处理不同类型的对象,例如:

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

上述代码使用qobject_case()对obj进行了向QLabel和QPushButton的强制转换,如果转换成功,则设置对应的显示文本。

四、小生总结

在实际Qt开发过程中,虽然可以在没有Q_OBJECT宏和元对象代码的情况下将QObject作为基类,但如果没有使用Q_OBJECT宏,则信号和槽函数机制或在本文中描述的其他特性都不能使用。从元对象系统的角度来看,一个没有元代码的QObject子类等价于它最近的有元对象代码的祖先。这意味着,例如,QMetaObject::className()将不会返回自己类的实际名称,而是这个祖先的类名称。

因此,在实际Qt开发过程中,无论实际上是否使用了信号和槽函数机制,都强烈建议QObject的所有子类都使用Q_OBJECT宏。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 函数
    +关注

    关注

    3

    文章

    3882

    浏览量

    61310
  • 代码
    +关注

    关注

    30

    文章

    4556

    浏览量

    66797
  • Meta
    +关注

    关注

    0

    文章

    164

    浏览量

    11180
  • 编译器
    +关注

    关注

    1

    文章

    1577

    浏览量

    48625
  • Qt
    Qt
    +关注

    关注

    1

    文章

    299

    浏览量

    37340

原文标题:Qt“灵魂”之Meta-Object系统

文章出处:【微信号:嵌入式小生,微信公众号:嵌入式小生】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    【AWorks试用体验】学习笔记(3)一个关于 Qt 的 demo

    器。Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,易于扩展,允许组件编程。2008年,奇趣科技被诺基亚公司收购,
    发表于 09-03 19:51

    做仪表的,用qt怎么做的?

    fsl-imx-fb-glibc-x86_64-meta-toolchain-qt5-cortexa9hf-neon-toolchain-4.1.15-2.1.0报错:/mnt/hgfs/zlmQtAPP/opengl/hellowindow/hellowindow.h:86: error
    发表于 12-21 10:22

    qt creator编译QT5应用

    +xfsl-imx-fb-glibc-x86_64-meta-toolchain-qt
    发表于 05-05 15:17

    如何对meta-toolchain-qt5进行bitbake?

    大家好,我设法在我的 STM32MP157C-DK2 上构建了具有一些额外图像功能的 st-example-image-qt。现在我只想运行 bitbake meta-toolchain-qt5 但构建最终会出现我无法解决的错误。当我尝试构建它时,我附上了输出控制台。你知
    发表于 02-07 10:14

    Qt 跨平台C++图形用户界面应用程序开发框架

    的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,Qt很容易扩展,并且允许真正地组件编程。
    发表于 03-28 21:03

    Yocto添加meta-webkit层时出现do_compile错误怎么解决?

    大家好,我正在研究 VAR-SOM IMX8,我正在构建 Qt5 图像,yocto 版本是dunfell-fslc-5.4-2.1.x-mx8-v1.5。当我尝试将 meta-webkit 层添加到
    发表于 03-30 07:45

    【米尔MYD-JX8MMA7开发板-ARM+FPGA架构试用体验】十一、QT-HMI V2.0系统

    代码进行方便的交互,使用起来非常方便。QMl是一种高效的开发UI 的语言。QML(Qt Meta-Object Language,Qt元对象语言)是一种声明式编程语言,并且它是Qt框架
    发表于 05-23 09:34

    bitbake imx-image-full时出现qt6错误怎么解决?

    /imx-yocto-bsp/sources/meta-qt6/recipes-qt/qt6/qtbase_git.bb: do_compile) 失败,退出代码为“1” 有什么办法可以解决这个问题吗?谢谢
    发表于 05-29 08:11

    Java Object Serialization Spec

    Java Object Serialization SpecificationObject serialization in the Java™system is the process
    发表于 10-14 17:39 7次下载

    什么是CORBA (Common Object Reques

    什么是CORBA (Common Object Request Broker Architecture)  英文缩写: CORBA (Common Object Request Broker Architecture) 中文译名: 通用对象请求
    发表于 02-22 11:48 888次阅读

    qt4图形设计与嵌入式开发

    生成扩展(称为元对象编译器(meta object Compiler moc))以及一些宏,易于扩展,允许组件编程。
    发表于 11-18 16:59 10次下载

    基于ARM和Qt的液氨罐区监控系统的设计_娄海强

    基于ARM和Qt的液氨罐区监控系统的设计_娄海强
    发表于 02-07 18:11 1次下载

    物联网软件系统中的关键和灵魂是什么

    RFID中间件是物联网软件系统中的关键和灵魂,为解决分布异构问题,人们提出了中间件的概念。
    发表于 11-19 09:29 2651次阅读

    Windows下的QT系统开发环境搭建

    生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,Qt很容易扩展,并且允许真正地组件编程。
    的头像 发表于 05-17 11:39 2267次阅读
    Windows下的<b class='flag-5'>QT</b><b class='flag-5'>系统</b>开发环境搭建

    Object类中的所有方法

    Object 类属于 java.lang 包,此包下的所有类在使用时无需手动导入,系统会在程序编译期间自动导入。Object 类是所有类的基类,当一个类没有直接继承某个类时,默认继承Objec
    的头像 发表于 10-13 11:50 276次阅读
    <b class='flag-5'>Object</b>类中的所有方法