Qt扫盲-Qt元对象系统记录-创新互联

Qt 元对象系统记录
  • 一、概述

成都创新互联公司专业为企业提供四方台网站建设、四方台做网站、四方台网站设计、四方台网站制作等企业网站建设、网页设计与制作、四方台企业网站模板建站服务,十多年四方台做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。一、概述

Qt的元对象系统提供了对象间通信的信号和槽机制、运行时类型信息和动态属性系统。就是动态的获取一些对象属性之类的,我经常会用到。

元对象系统基于三件事:

  1. QObject类为可以利用元对象系统的对象提供了一个基类。
  2. 类声明的private段中的Q_OBJECT宏用于启用元对象特性,如动态属性、信号和槽。
  3. 元对象编译器(moc)为每个QObject子类提供了实现元对象功能所需的代码。

这个就是要求我们在写自己的类的时候要继承 自 QObject 同时添加 Q_OBJECT 宏就好。

moc工具读取 c++ 源文件。如果它找到一个或多个包含 Q_OBJECT 宏的类声明,它会生成另一个包含每个类的元对象代码的c++源文件。这个生成的源文件要么 #include 到类的源文件中,要么,更常见的是,编译并链接到类的实现。
除了提供对象之间通信的信号和槽机制(引入该系统的主要原因),元对象代码还提供了下列额外功能。

  • QObject::metaObject() 返回类的关联元对象,这个元对象属性。
QObject *obj = new QPushButton;
obj->metaObject()->className();             // returns "QPushButton"

QPushButton::staticMetaObject.className();  // returns "QPushButton"
  • QMetaObject::className()在运行时以字符串的形式返回类名,而不需要c++编译器对原生运行时类型信息(RTTI)的支持。
  • QObject::inherits() 函数返回一个对象是否是QObject继承树中继承指定类的类的实例。
QTimer *timer = new QTimer;         // QTimer inherits QObject
timer->inherits("QTimer");          // returns true
timer->inherits("QObject");         // returns true
timer->inherits("QAbstractButton"); // returns false

// QVBoxLayout inherits QObject and QLayoutItem
QVBoxLayout *layout = new QVBoxLayout;
layout->inherits("QObject");        // returns true
layout->inherits("QLayoutItem");    // returns true (even though QLayoutItem is not a QObject)
  • QObject::tr() 和 QObject::trUtf8() 将字符串转换为国际化。
  • QObject::setProperty() 和 QObject::property() 动态地通过名称设置和获取属性。
  • QMetaObject::newInstance() 构造类的一个新实例。

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

例如,假设MyWidget继承自QWidget,并用Q_OBJECT宏声明:

QObject *obj = new MyWidget;

类型为QObject *的obj变量实际上引用了一个MyWidget对象,因此我们可以适当地校正它:

QWidget *widget = qobject_cast(obj);

从QObject转换到QWidget是成功的,因为对象实际上是一个MyWidget,它是QWidget的子类。因为我们知道obj是一个MyWidget,我们也可以将它强制转换为MyWidget *:

MyWidget *myWidget = qobject_cast(obj);

转换到MyWidget是成功的,因为qobject_cast()没有区分内置Qt类型和自定义类型。

QLabel *label = qobject_cast(obj);
// label is 0

另一方面,转换为QLabel会失败。接下来,该指针设置为0。这使得可以在运行时根据类型以不同的方式处理不同类型的对象:

if (QLabel *label = qobject_cast(obj)) 
{  label->setText(tr("Ping"));
} else if (QPushButton *button = qobject_cast(obj)) 
{  button->setText(tr("Pong!"));
}

虽然可以在没有Q_OBJECT宏和元对象代码的情况下使用QObject作为基类,但如果没有使用Q_OBJECT宏,则信号和插槽以及这里描述的其他功能都不可用。从元对象系统的角度来看,没有元代码的QObject子类等同于它有元对象代码的最近的祖先。这意味着,例如,QMetaObject::className()不会返回你的类的实际名称,而是这个祖先的类名。
因此,我们强烈建议QObject的所有子类使用Q_OBJECT宏,无论它们是否实际使用信号、槽和属性。

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网站标题:Qt扫盲-Qt元对象系统记录-创新互联
本文路径:http://cdiso.cn/article/deojij.html

其他资讯