简述

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

元对象系统基于三个方面:

  • QObject类:为objects提供了一个可以利用元对象系统的基类。

  • Q_OBJECT宏: 在类的私有部分声明这个宏可以启用元对象特性,例如:动态属性、信号与槽。

  • Meta-Object编译器(moc): 为每个QObject子类生成必要的代码来实现元对象特性。

moc工具会读取C++源文件,如果发现有包含Q_OBJECT宏的类声明,就生成另外一个包含这些类的元对象代码的C++源文件。生成的源文件要么在类源文件里用#include包含,或者(更常见)与类的实现代码直接进行编译连接。

moc工具会读取C++源文件,如果发现一个或者多个声明了Q_OBJECT宏的类,就生成另外一个包含这些类的元对象代码的C++源文件。这些编译生成的源文件要么被包含到类的源文件中,或者更常见,被编译和链接到类的实现中。

详细描述

除了为对象间的通信提供信号与槽(引入元对象系统的主要原因)机制外,元对象还提供以下特性:

  • QObject::metaObject()返回类关联的meta-object对象。

  • QMetaObject::className()在运行时以字符串的形式返回类名,无需C++编译器提供运行时类别信息(RTTI)的支持。

  • QObject::inherits()返回一个对象是否是QObject继承树上一个类的实例。

  • QObject::tr()和QObject::trUtf8()提供国际化支持,将字符串翻译成指定的语言。

  • QObject::setProperty()和QObject::property()通过名称动态设置和获取属性。

  • QMetaObject::newInstance()构造类的一个新实例。

除此之外,还可以用qobject_cast()动态转换QObject类的类型。qobject_cast()函数和标准C++的dynamic_cast()功能类似,它的优点在于:不需要RTTI的支持,而且可以跨越动态连接库的转换。它尝试将它的参数转换成尖括号内的指针类型,如果对象是正确的类型(在运行时检查),则返回非零指针;否则,返回0,说明对象类型不兼容。

例如,假设MyWidget继承自QWidget,同时也声明了Q_OBJECT宏。

QObject *obj = new MyWidget;

QObject *类型的变量obj实际上指向一个MyWidget对象,因此,我们可以适当地进行类型转换:

QWidget *widget = qobject_cast<QWidget *>(obj);

因为obj实际上是一个MyWidget,而MyWidget是QWidget的子类,所以,从QObject转换为QWidget成功了。既然知道了obj是MyWidget类型的,那么我们也可以将其转换为MyWidget *:

MyWidget *myWidget = qobject_cast<MyWidget *>(obj);

到MyWidget类型的转换也是成功的,因为qobject_cast()并不区分内建的Qt类型和自定义类型。

QLabel *label = qobject_cast<QLabel *>(obj);
// label 为 0

可是,转换到QLabel却失败了,返回的指针为0。这使得我们可以在运行时根据对象的类型而做不同的操作:

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宏(即:不用任何元对象代码)的情况下仍旧使用QObject作为基类,但是像信号和槽以及上面所说的其它特性都将无法使用。从元对象系统的角度来看,一个没有元对象代码的QObject子类等同于它最接近的有元对象代码的祖先。这意味着,QMetaObject::className()将不会返回你的类的真实名称,而是返回其祖先的名字。

因此,强烈建议所有QObject的子类都使用Q_OBJECT宏,不管实际上是否使用信号和槽,以及属性。

更多参考

  • The Meta-Object System - 助手

Qt之Meta-Object系统的更多相关文章

  1. Qt Meta Object System-元对象系统

    研一的时候开始使用Qt,感觉用Qt开发图形界面比MFC的一套框架来方便的多.后来由于项目的需要,也没有再接触Qt了.现在要重新拾起来,于是要从基础学起. Now,开始学习Qt事件处理机制. 元对象系统 ...

  2. 6、Qt Meta Object system 学习

    原文地址:http://blog.csdn.net/ilvu999/article/details/8049908 使用 meta object system 继承自 QOject 类定义中添加 Q_ ...

  3. Qt Meta Object system 学习

    原文地址:http://blog.csdn.net/ilvu999/article/details/8049908 使用 meta object system 继承自 QOject 类定义中添加 Q_ ...

  4. Qt元对象(Meta-Object)系统与反射

    反射 -在计算机科学中,反射是指计算机程序在运行时(Run time)可以访问.检测和修改它本身状态或行为的一种能力.[1]用比喻来说,反射就是程序在运行的时候能够“观察”并且修改自己的行为. 要注意 ...

  5. C++框架_之Qt的窗口部件系统的详解-上

    C++框架_之Qt的窗口部件系统的详解-上 第一部分概述 第一次建立helloworld程序时,曾看到Qt Creator提供的默认基类只有QMainWindow.QWidget和QDialog三种. ...

  6. Qt笔记——元对象系统

    Qt元对象系统提供了对象间的通信机制:信号和槽.以及执行类形信息和动态属性系统的支持.是标注C++的一个扩展,它使得Qt可以更好的实现GUI图形用户界面编程.Qt的元对象系统不支持C++模板.虽然模板 ...

  7. Qt 中的属性系统(Property System)

    21 人赞同了该文章 本节内容主要讲解我对 Qt 属性系统的理解.官方文档参考 The Property System. 如何理解"属性系统"这个概念? 一般我们说一个类有什么属性 ...

  8. Qt之国际化(系统文本-QMessageBox按钮、QLineEdit右键菜单等)

    简介 使用Qt的时候,经常会遇到英文问题,例如:QMessageBox中的按钮.QLineEdit.QSpinBox.QScrollBar中的右键菜单等.通常情况下,我们软件都不会是纯英文的,那么如何 ...

  9. 关于QT应用在XP系统上兼容运行的问题

    修改兼容XP: 1. 项目属性->配置属性->平台工具集:Visual Studio 2013 - Windows XP (v120_xp) 2. C/C++ 属性-> 代码生成-& ...

  10. Qt 绘图与动画系统

    Qt 提供了内置的绘图系统以及独立的QtOpenGL模块提供对OpenGL的支持.Qt提供了基于状态机的QPainter系统和面向对象的Graphics View系统. QPainter 基于状态机的 ...

随机推荐

  1. Java——再看IO

    一.编码问题 utf-8编码中,一个中文占3个字节,一个英文占1个字节:gbk编码中,一个中文占2个字节,一个英文占1个字节. Java是双字节编码,为utf-16be编码,是说一个字符(无论中文还是 ...

  2. hihoCoder太阁最新面经算法竞赛17

    比赛链接:http://hihocoder.com/contest/hihointerview26 A.排序后枚举两个点,确定一个矩形后二分剩下两个点. #include <bits/stdc+ ...

  3. Java代码规范性

    ---------------------------------------------------------------------------------------------------- ...

  4. 【面向打野编程】——KMP算法入门

    一.问题 咱们先不管什么KMP,来看看怎么匹配两个字符串. 问题:给定两个字符串,求第二个字符串是否包含于第一个字符串中. 为了具体化,我们以 ABCAXABCABCABX 与 ABCABCABX为例 ...

  5. canvas背景透明

    var can=document.getElementById("canv"); c=can.getContext("2d"); c.globalAlpha=. ...

  6. 自定义表单input

    我想实现下面这个效果?应该怎么写最方便呢?最有效,兼容性最好呢 我使用<p>标签套lable,加input的组合,p标签绝对定位,input标签铺满,用padding填充. 主要css . ...

  7. 输出sed的重定向

    默认情况下,sed编辑器会将进步的结果输出到STDOUT上,你可以在shll脚本中使用所有重订向sed编辑器输出的标准方法. 你可以在脚本中用反引号来将sed编辑器命令的输出重定向到一个变量中供后面使 ...

  8. mysq错误(1)空用户创建库

    mysql5.6.24免安装版: 1.ERROR 1044 (42000): Access denied for user ''@'localhost' to database 现象:创建库失败. 出 ...

  9. ip地址的组成(网络位+主机位)

    IP地址子网掩码都是32位的2进制,为了方便记忆转成10进制,通过子网掩码来区分网络位和主机位,子网掩码跟IP地址一一对应,子网掩码为1的是网络位,为0的是主机位.如:192.168.1.2 掩码25 ...

  10. Css_Backgroud-position(背景图片)定位问题详解

    background-position的说明:    设置或检索对象的背景图像位置.必须先指定 background-image 属性.该属性定位不受对象的补丁属性( padding )设置影响.   ...