Qt扫盲-Qt元对象系统记录-创新互联
- 一、概述
Qt的元对象系统提供了对象间通信的信号和槽机制、运行时类型信息和动态属性系统。就是动态的获取一些对象属性之类的,我经常会用到。
元对象系统基于三件事:
- QObject类为可以利用元对象系统的对象提供了一个基类。
- 类声明的private段中的Q_OBJECT宏用于启用元对象特性,如动态属性、信号和槽。
- 元对象编译器(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元对象系统记录-创新互联
链接URL:http://scyanting.com/article/deojij.html