精华内容
下载资源
问答
  • Qt 元对象系统

    千次阅读 2021-05-02 16:53:35
    Qt元对象系统(Meta-Object System)提供了对象之间通信的信号与槽机制、运行时类型信息和动态属性系统。 元对象系统由以下三个基础组成: QObject 类,是所有使用元对象系统的类的基类。换句话说只有继承 ...

    作者:billy
    版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

    什么是 Qt 元对象系统

    Qt 的元对象系统(Meta-Object System)提供了对象之间通信的信号与槽机制、运行时类型信息和动态属性系统

    元对象系统由以下三个基础组成:

    1. QObject 类,是所有使用元对象系统的类的基类。换句话说只有继承 QObject 才能使用元对象系统;
    2. Q_OBJECT 宏,在一个类的 private 部分声明 ,使得类可以使用元对象的特性,如动态属性、信号与槽;
    3. MOC(元对象编译器),为每个 QObject 的子类提供必要的代码来实现元对象系统的特性。构建项目时,MOC 工具读取 C++ 源文件,当它发现类的定义里有 Q_OBJECT 宏时,它就会为这个类生成另外一个包含有元对象支持代码的 C++ 源文件,这个生成的源文件连同类的实现文件一起被编译和连接。通常这个新的C++原文件会再以前的C++原文件前面加上moc_作为新的文件名;

    元对象系统的功能

    除了提供在对象间通讯的机制外,元对象系统还包含以下几种功能:

    1. QObject::metaObject()方法,获得与一个类相关联的meta-object;
    2. QMetaObject::className()方法,在运行期间返回一个对象的类名,不需要本地C++编译器的 RTTI(run time type information)支持;
    3. QObject::inherits()方法,用来判断一个对象的类是不是从一个特定的类继承而来;
    4. QObject::tr()、QObject::trUtf8()方法,为软件的国际化翻译字符串;
    5. QObject::setProperty()、QObject::property()方法,根据属性名动态的设置和获取属性值;
    6. QMetaObject::newInstance()方法,构造类的新实例;
    7. 使用 qobject_cast()方法可以在在 QObject 类之间提供动态转换,qobject_cast()方法的功能类似于标准 C++ 的 dynamic_cast(),但是 qobject_cast() 不需要RTTI的支持。在一个 QObject 类或者它的派生类中,如果不定义 Q_OBJECT 宏,那么这些功能将不能被使用。从 meta-object 的观点来看,一个没有定义 Q_OBJECT 宏的类与它最接近的那个祖先类是相同的。那么 QMetaObject::className() 方法返回的名字并不是该类的名字,而是与它最近接的那个祖先类的名字。所以,任何从 QObject 继承的类都必须定义 Q_OBJECT 宏

    Meta Object 的所有数据和方法都封装在 QMetaObject 类中,它包含一个 Qt 类的 meta 信息,并且提供查询功能。meta 信息包含:

    1. 信号表(signal table),与对应 Qt 类相关的系统定义及自定义的 signal 的名字;
    2. 槽表(slot table),与对应 Qt 类相关的系统定义及自定义的 slot 的名字;
    3. 类信息表(class info table),Qt 类的类型信息;
    4. 属性表(property table),与对应类中的所有属性的名字;
    5. 指向 parent meta object 的指针;

    Q_OBJECT 宏的定义

    Q_OBJECT 定义在 /src/corelib/kernel/Qobjectdefs.h 文件中,Q_OBJECT 宏的定义如下:

    #define Q_OBJECT \
    public: \
        Q_OBJECT_CHECK \
        static const QMetaObject staticMetaObject; \
        Q_OBJECT_GETSTATICMETAOBJECT \
        virtual const QMetaObject *metaObject() const; \
        virtual void *qt_metacast(const char *); \
        QT_TR_FUNCTIONS \
        virtual int qt_metacall(QMetaObject::Call, int, void **); \
    private: \
        Q_DECL_HIDDEN static const QMetaObjectExtraData staticMetaObjectExtraData; \
        Q_DECL_HIDDEN static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
    

    QMetaObject 类型的静态成员变量 staticMetaObject 是元数据的数据结构。metaObject,qt_metacast,qt_metacall、qt_static_metacall 四个虚函数由 MOC 在生成的 moc_xxx.cpp 文件中实现。
    1)metaObject 的作用是得到元数据表指针;
    2)qt_metacast 的作用是根据签名得到相关结构的指针,返回void*指针;
    3)qt_metacall 的作用是查表然后调用调用相关的函数;
    4)qt_static_metacall 的作用是调用元方法(信号和槽);

    元对象编译器 MOC

    1. MOC 的功能
      1)处理 Q_OBJECT 宏和 signals/slots 关键字,生成信号和槽的底层代码;
      2)处理 Q_PROPERTY() 和 Q_ENUM() 生成 property 系统代码;
      3)处理 Q_FLAGS() 和 Q_CLASSINFO() 生成额外的类 meta 信息;
      4)不需要 MOC 处理的代码可以用预定义的宏括起来,如下:
    #ifndef Q_MOC_RUN
    …
    #endif
    
    1. MOC 的限制
      1)模板类不能使用信号/槽机制;
      2)MOC不扩展宏,所以信号和槽的定义不能使用宏, 包括 connect 的时候也不能用宏做信号和槽的名字以及参数;
      3)从多个类派生时,QObject 派生类必须放在第一个。 QObject(或其子类)作为多重继承的父类之一时,需要把它放在第一个。 如果使用多重继承,MOC 在处理时假设首先继承的类是 QObject 的一个子类,需要确保首先继承的类是 QObject 或其子类;
      4)函数指针不能作为信号或槽的参数, 因为其格式比较复杂,MOC 不能处理。可以用typedef 把它定义成简单的形式再使用;
      5)用枚举类型或 typedef 的类型做信号和槽的参数时,必须 fully qualified。这个词中文不知道怎么翻译才合适,简单的说就是,如果是在类里定义的,必须把类的路径或者命名空间的路径都加上, 防止出现混淆。如 Qt::Alignment 之类的,前面的 Qt 就是 Alignment 的 qualifier;
      6)信号和槽不能返回引用类型;
      7)signals 和 slots 关键字区域只能放置信号和槽的定义,不能放其它的如变量、构造函数的定义等,友元声明不能位于信号或者槽声明区内;
      8)嵌套类不能含有信号和槽 ;

    2. 自定义类型的注册
      Qt 线程间传递自定义类型数据时,自己定义的类型如果直接使用信号槽来传递的话会产生下面这种错误:
      QObject::connect: Cannot queue arguments of type 'XXXXX' (Make sure 'XXXXX' is registed using qRegisterMetaType().)

    错误原因:当一个 signal 被放到队列中(queued)时,参数(arguments)也会被一起放到队列中,参数在被传送到 slot 之前需要被拷贝、存储在队列中;为了能够在队列中存储参数,Qt 需要去 construct、destruct、copy 参数对象,而为了让 Qt 知道怎样去作这些事情,参数的类型需要使用 qRegisterMetaType 来注册;

    注册自定义类的步骤如下:
    1)自定义类型时在类的顶部包含:#include ;
    2)在类型定义完成后,加入声明:Q_DECLARE_METATYPE(XXX);
    3)在 main() 函数中注册自定义类类型:qRegisterMetaType(“XXX”),如果希望使用类型的引用,同样要注册:qRegisterMetaType(“XXX&”);

    展开全文
  • 本文讲述如何注册自定义类型到Qt元对象系统中和它又有什么用。

    本文讲述如何注册自定义类型到Qt元对象系统中和它有什么作用。

    注册自定义结构体为例

    1. 使用Q_DECLARE_METATYPE标记自定义类型;
    #include <QMetaType>
    struct MyStruct {
        QString name;
        QString color;
    };
    
    Q_DECLARE_METATYPE(MyStruct)
    
    1. 在main函数中使用qRegisterMetaType注册自定义类型到元对象系统中。
    int main(int argc, char *argv[]) {
        ...
        qRegisterMetaType<MyStruct>();
        ...
        return 0;
    }
    
    

    作用

    • Q_DECLARE_METATYPEQ标记的类型可以让QMetaType查询到类型,也可以让QVariant识别到。例如:
    MyStruct myStruct;
    QVariant variant;
    variant.setValue(myStruct); // 不使用Q_DECLARE_METATYPEQ标记的自定义类型会出现编译错误。
    ...
    MyStruct myStruct2 = variant.value<MyStruct>();
    ...
    
    • 使用qRegisterMetaType注册自定义类型到元对象系统中主要作用为QObject的属性系统(信号槽)中使用该自定义类型。
    展开全文
  • Qt 使用笔记:面试Qt开发元对象系统 和 信号槽Qt元对象系统信号槽解 实现方式       Qt元对象系统   Qt作为一个软件开发框架,搞了一套魔法糖便于UI开发。引入了元对象系统,提供了:对象树、信号槽、动态属性...

      就职于一个小的桌面软件开发公司。业务拓展,最近需要招几个小伙伴,让我这个半吊子去面试。我干脆直接搞份简历去规模差不多的其他公司面试看看别人问些什么。元对象系统 和 信号槽是问的最多的。针对问题自己记录下,有错误请指正。
      参考:
    QT学习——Qt信号与槽实现原理
    Qt信号槽-原理分析


    Qt 使用笔记:面试Qt开发元对象系统 和 信号槽


      
      

    Qt元对象系统

      Qt作为一个软件开发框架,搞了一套魔法糖便于UI开发。引入了元对象系统,提供了:对象树、信号槽、动态属性这三个功能,极大的加快ui开发。

    • 对象树 解决问题 :无需考虑回收、可以随时获取父类和子类并操作。
    • 动态属性 解决问题 :配合样式表和事件过滤器,对于UI开发实在是爽。
    • 信号槽 解决问题 :松散耦合+类型安全。观察者模式,调用函数指针。

      元对象系统和MOC预处理器是为了在c++内引入反射机制。
      反射(内省)机制:程序运行时,对于任何一个类,能够知道有哪些方法和属性;对于任何一个对象,能够随时调用方法和属性。动态获取对象信息和调用对象方法的功能称为反射机制。

    在这里插入图片描述
      
      
      
      

    信号槽解 实现方式

    • 声明:信号和槽
        信号和槽是一回事就是回调函数(无论那种链接)。信号自己声明,moc帮你实现;槽自己声明自己实现或者lambda。除此之外完全一样。

    • 声明:moc做了什么
        moc构建回调的开头和结尾
        回调过程QOjbect宏中实现
        signalsslots宏帮助区分信号和槽

    • 声明:自定义数据类型
        信号槽只能传递MetaTypeqRegisterMetaType注册一下。

    • 链接:connect
        把发送、信号、接收、槽四者绑定,存到发射者内部,供后续执行信号时查找。信号槽链接方式5种:

    链接方式描述
    自动同线程同步,跨线程异步。调用槽函数(回调)
    直连同线程同步。调用槽函数(回调)
    队列跨线程异步。调用槽函数(回调)
    阻塞队列跨线程同步。调用槽函数(回调)
    唯一防止重复链接,前四种是互斥的,这个跟前几个任意组合

    在这里插入图片描述

    • 触发:发送信号
        发射者内部获取信号对应的QObjectConnectionListVector,执行一系列回调函数。跨线程的话就是抛出QMetaCallEvent把这个函数丢到队列里,放入Qt本身的事件循环中。

    在这里插入图片描述


    展开全文
  • 解析Qt元对象系统(一) 概述

    千次阅读 2018-07-21 10:53:12
    Meta-Object System 提供了Qt的信号和槽机制以及对象之间的互相通信,运行时的信息和动态属性系统。 三个必要条件: 1. QObject的子类 2. 宏Q_OBJECT 3. Meta Object Compiler Qt官方建议对自定义的QObject子类...

    Meta-Object System 提供了Qt的信号和槽机制以及对象之间的互相通信,运行时的信息和动态属性系统。

    三个必要条件:
    1. QObject的子类
    2. 宏Q_OBJECT
    3. Meta Object Compiler

    Qt官方建议对自定义的QObject子类都要加这个宏,但要注意:某些类不是继承自QObject,这些类里加Q_OBJECT就会出错,例如QEvent,QGraphicsItem,QRunnable.

    MOC的实现是一个预处理器,使用MOC的方式,所有平台上的标准的C++编译器都能支持Qt。从而不需要实现一个新的跨平台的Qt编译器。moc是为了解决反射的问题,但是一些动态的编程语言(如Python,Ruby等)中,语言本身自带反射功能。Qt程序之所以编译速度慢,主要是因为在 Qt 将源代码交给标准C++编译器,如gcc之前,需要事先将这些扩展的语法去除掉。完成这一操作的就是 moc。

    如果工程是用qmake生成Makefile进行编译,那么其中就包含了调用moc的规则,我们不必直接使用moc.exe。moc.exe会读取头文件,查看是否有Q_OBJECT宏定义,如果有则根据这个头文件生成相应的moc_.cpp,该文件同样将进入编译系统,最终被链接到二进制代码中去,QtCreator生成的代码就是通过编译链接时,把moc_widget.o与其他目标文件链接到一起,这种方式不用改源代码,相对而言比较顺眼。

    moc_.cpp主要实现了头文件中的Q_OBJECT宏和SIGNAL,也就是将Qt扩展的语法去掉,再交给C++编译器。
    SIGNAL只在头文件做声明,但我们写Qt程序时从不进行实现,因为它是在moc_.cpp里实现的,
    例如无参数信号void Text();的实现:

    void MainWindow::Text()
    {
        QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
    }

    有参数信号void time(QDateTime t);的实现:

    void MainWindow::time(QDateTime _t1)
    {
        void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
        QMetaObject::activate(this, &staticMetaObject, 1, _a);
    }

    主要调用QMetaObject::activate方法,staticMetaObject是这个类默认的一个静态元对象。第三个参数是信号对应的序数。第四个参数如果是nullptr则代表信号无参数,否则代表参数的指针。

    moc文件也可以在cpp文件中被include,Qt官方示例很多就是这样做的,我们也可以这样写常见的MainWindow程序:

    #include <QApplication>
    #include <QMainWindow>
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    public:
        explicit MainWindow(QWidget *parent=0):
            QMainWindow(parent)
        {}
        ~MainWindow()
        {}
    };
    
    #include "main.moc"
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow m;
        m.resize(800,600);
        m.show();
        return a.exec();
    }

    编译之前先运行qmake,以处理宏Q_OBJECT,生成main.moc。如果没有#include "main.moc",会报错:
    无法解析3个外部符号,即moc文件中实现的3个函数:qt_metacall, qt_metacast, metaObject

    元对象系统涉及到的类: QMetaType, QMetaMethod, QMetaObject, QMataClassInfo, QMetaEnum, QMetaDataReaderControl, QMetaProperty,

    QMataType是Qt所支持的元类型,有个Type的枚举,这个枚举列表中的所有类型是Qt信号槽机制本身就支持的,大部分的类型实际在宏QT_FOR_EACH_STATIC_TYPE中包含。如果是自定义的类型需要用qRegisterMetaType去注册元类型才能被Qt的信号槽所识别。

    QMetaMethod有个重要的成员函数invoke,支持跨线程调用,是基于元对象系统的。

    QMetaObject是元对象类本身,实现了QMetaObject::invokeMethod, 功能和QMetaMethod没有什么区别。提供了元对象系统的基本方法,包括方法/信号槽/属性的数目/序数等等方法。

    QMataClassInfo提供了类的附加信息。

    元对象系统的一些常用工具:

    • QObject::metaObject(),返回当前类的元对象信息,是个QMetaObject指针;QObject::staticMetaObject也可以获取当前类的元对象信息,类型是QMetaObject。
    • QMetaObject::className(),运行时返回类名,返回类型是char*。
    • QMetaObject::newInstance(),构造一个新的实例。
    • QObject::inherits(),判断当前对象实例的类继承关系,常用于判断某个对象属于哪个类。
    • QObject::tr() 和QObject::trUtf8()用于Qt语言国际化,返回类型是QString。
    • QObject::property()/setProperty(),通过属性名动态获取/修改属性值。
    • qobject_cast(),动态类型转换,类似于标准C++的dynamic_cast(),不同的是它不需要RTTI(run time type information)且不受动态库的限制。
    展开全文
  • 解析Qt元对象系统(三) 信号与槽

    千次阅读 2018-07-21 10:54:02
    引述 ...先运行一个普通的QWidget程序,添加一个按钮,定义一个槽函数test,函数体里做个断点,调试运行,...元对象系统的调用层次如下 QAbstractButtonPrivate::click和QAbstractButtonPrivate::emitClicked属于源...
  • 使用Q_INVOKABLE来修饰成员函数,目的在于被修饰的成员函数能够被元对象系统所唤起。 Q_INVOKABLE与QMetaObject::invokeMethod均由元对象系统唤起。这一机制在Qt C++/QML混合编程,跨线程编程,Qt Service ...
  • Qt元对象系统解析(一)

    万次阅读 多人点赞 2016-05-06 15:43:17
    Qt信号与槽是一个很好机制,不如说Qt元对象系统很强大。这也是大家讲Qt就必须将信号与槽,讲信号与槽就要讲Qt元对象系统。当然初学者知道怎么用就OK啦,当然随着你写的代码越多,接触的平台越多的时候,你就会...
  • QT】什么是Qt元对象系统

    千次阅读 2015-01-15 17:45:29
    Qt对象系统,即meta ...一是QObject类,是所有Qt对象的基类,可以很好的使用mos。 二是Q_OBJECT宏,在类private部分声明,用于激活mos特性,例如动态属性、信号与槽。 三是对象编译器,即meta object comp
  • QT 本身不是一种编程语言,它实质上是一个跨...QT元对象编译器(Meta-Object Compiler, MOC)是一个预处理器,在源程序编译前,先将这些QT特性的程序转换为标准的C++兼容的形式,然后再有C++编译器进行编译。这就...
  • Qt元对象系统和模板机制的冲突

    千次阅读 2013-06-07 18:51:24
    Qt对象系统是对为了Qt对象类型和信号与槽机制引进的,Qt的工具包中有一个对象编译器,它是为支持Qt对象系统而产生一些额外C++代码,这些编码会和源码一起被标准的C++编译器编译,因为Qt的这一套标准是不支持的...
  • Qt 元对象系统(Meta-Object System)

    万次阅读 2010-04-17 15:53:00
    Qt 元对象系统(Meta-Object System)Qt元对象系统基于如下三件事情:1. 类:QObject,为所有需要利用原对象系统的对象提供了一个基类。2. 宏:Q_OBJECT,通常可以声明在类的私有段中,让该类可以使用元对象对象的...
  • QT中的 元对象系统

    千次阅读 2019-02-20 15:40:13
     QT中的 元对象系统(Meta-Object System)提供了对象间通信的信号槽机制、运行时类型信息和动态属性属性系统,元对象系统是基于以下三个条件的:  1、该类必须继承自Qobject类  2、必须在类的私有声明区声明Q_...
  • 这也是大家讲Qt就必须将信号与槽,讲信号与槽就要讲Qt元对象系统。当然初学者知道怎么用就OK啦,当然随着你写的代码越多,接触的平台越多的时候,你就会好奇Qt是如何把两个(多个)任意不相关(必须都继承与...
  • 元对象系统涉及很多方面,比如运行时类信息,属性信息,信号槽等等,但是其中最主要的应该是信号槽,大家也许在处理信号槽的时候都碰到过这么一个问题:为什么我没加Q_OBJECT宏,信号槽就生效不了呢?进入正题:#...
  • 解析Qt元对象系统(二) Q_OBJECT

    千次阅读 2018-07-21 10:53:37
    Q_OBJECT宏的定义在qobjectdefs.h: #define Q_OBJECT \ ... QT_WARNING_PUSH \ Q_OBJECT_NO_OVERRIDE_WARNING \ static const QMetaObject staticMetaObject; \ virtual const QMetaObject *met...
  • QT中元对象系统(MOC)原理

    千次阅读 2017-07-27 10:44:44
    元对象系统这样工作: ● Q_OBJECT宏声明一些内省函数(metaObject(),TR(),qt_matacall()和少量其他的函数)。这些函数必须在所有的QObject的子类中被实现。 ● Qt的moc工具负责执行被Q_OBJECT宏声明的函
  •  QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数QT源码解析(二)深入剖析QT元对象系统和信号槽机制QT源码解析(三)深入剖析QT元对象系统和信号槽机制(续)QT源码解析(四)剖析Qt的事件机制原理QT源码解析
  • Qt 已注册元对象类型

    千次阅读 2013-11-20 10:55:06
    Qt内置了一部分元对象类型,如果下列不包含的元对象,在信号槽或者QVariant中必须注册。 注册方法: int id = qRegisterMetaTypeMyStruct>();
  • Qt 元对象机制

    千次阅读 2012-09-22 14:52:50
    Qt之所以能有很大的动态性,都源自于它的元对象系统。下面是对这个机制的一个简要介绍。(来自于C++ GUI Programing with Qt4) Qt的一个最主要的特点可能就是它扩展了C++的机制,可以创建独立的软件组件,...
  • Qt元系统之类型注册

    千次阅读 2017-04-20 18:03:07
    Qt元系统之类型注册Qt元系统之类型注册 Meta Type System 场景 原因 实现细节 QMetaTyperegisterNormalizedType函数 QMetaTypeFunctionHelper模板类 QCustomTypeInfo类 source codeMeta Type System 如果库或程序有...
  • Qt 源码之元对象(QMetaObject)

    千次阅读 2014-11-29 21:03:07
    1、 简述:QMetaObject是用来保存Qt元对象信息,当继承QObject类并使用宏Q_OBJECT时,创建的类产生一个静态QMetaObject实例staticMetaObject,这个实例会保存类名、信号名称及索引、槽的名字及索引等等在对象...
  • QT_WARNING_PUSH \ Q_OBJECT_NO_OVERRIDE_WARNING \ static const QMetaObject staticMetaObject; \ virtual const QMetaObject *metaObject() const; \ virtual void *qt_metacast(const char *); \ virtual ...
  • 一、Qt主要工具介绍 ...6)qt元对象编译器(moc)//处理语法扩展 7)qt创造器IDE(qtcreator) 二、Qt助手的使用 例如:了解QApplication类的功能和作用 1)先看第一句话,了解该类的功能,在点击more...
  • qt对象销毁过程delete

    千次阅读 2018-07-17 10:26:44
    ... 在C++中学习过程中,我们都知道: delete 和 new 必须配对使用(一 一对应):delete少了,则内存泄露,多了麻烦更大。Qt作为C++的库,显然是不会违背C++的前述原则的。可...
  • Qt 对象数据的声明和使用

    千次阅读 2018-02-07 11:12:30
    Qt对象数据的声明和使用 作者: Venus  C++程序编译效率 每个C++类的写法通常情况下: class A { public:  void something(); private:  string m_Name; // 姓名  bool m_Sex; // 性别  ...
  •  作者:清林,博客名:飞空静渡我们在使用QT编程时,难免要定义自己需要的类型,但像QT自己的类型如QSzie、QString之类的,都是可以存储在QViriant中的,并且这些QT的类型是可以用在基于QObject类的类型属性中和...
  •  QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数QT源码解析(二)深入剖析QT元对象系统和信号槽机制QT源码解析(三)深入剖析QT元对象系统和信号槽机制(续)QT源码解析(四)剖析Qt的事件机制原理QT源码解
  • 01 QT窗口对象与子窗口对象

    千次阅读 2017-05-09 15:32:48
    创建QT的“qmake empty project”后, 有个pro文件. 此文件是用于管理工程,记录有哪些头文件,哪些源文件,使用了QT的哪些库, 不是写代码用的。一般情况下,不要修改它. pro文件里需要加上: QT += gui core //表示...
  • Qt根据属性判断对象的类型

    千次阅读 2020-08-17 17:32:52
    在使用Qt的过程中偶尔有需求需要动态判断当前对象的类型,比如模板类中若对不同的类型有特殊处理,需要用到此功能,Qt元对象系统提供了属性来进行判断 bool QObject::inherits(const char *className) const ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 81,503
精华内容 32,601
关键字:

qt元对象