An overview of Qt’s meta-object system and introspection capabilities.
Qt’s meta-object system provides the signals and slots mechanism for inter-object communication, run-time type information, and the dynamic property system.
元对象系统基于 3 件事:
QObject类为可以利用元对象系统的对象提供基类。
Q_OBJECT宏 (在类声明的私有部分内) 被用于启用元对象特征,如:动态特性、信号和槽。The Meta-Object Compiler (
moc) 供应每QObject子类采用必要代码,以实现元对象特征。
moc工具读取 C++ 源文件。若找到一个或多个类声明包含Q_OBJECT宏,它产生包含每个这些类的元对象代码的另一 C++ 源文件。这生成的源文件将#include‘d into the class’s source file or, more usually, compiled and linked with the class’s implementation.除了提供 信号和槽 机制用于对象之间的通信 (引入系统的主要原因),元对象代码提供以下额外特征:
metaObject()returns the associated元对象为类。
className()returns the class name as a string at run-time, without requiring native run-time type information (RTTI) support through the C++ compiler.
inherits()function returns whether an object is an instance of a class that inherits a specified class within theQObject继承树。
tr()andtrUtf8()translate strings for internationalization.
setProperty()andproperty()dynamically set and get properties by name.
newInstance()constructs a new instance of the class.也可以履行动态铸造使用
qobject_cast()onQObject类。qobject_cast()function behaves similarly to the standard C++dynamic_cast(), with the advantages that it doesn’t require RTTI support and it works across dynamic library boundaries. It attempts to cast its argument to the pointer type specified in angle-brackets, returning a non-zero pointer if the object is of the correct type (determined at run-time), orNoneif the object’s type is incompatible.For example, let’s assume
MyWidget继承自QWidget和声明采用Q_OBJECT宏:QObject *obj = new MyWidget;
obj变量,类型QObject *,实际引用MyWidget对象,因此可以适当铸造:QWidget *widget = qobject_cast<QWidget *>(obj);铸造从
QObjecttoQWidget成功,因为对象实际是MyWidget,这是子类对于QWidget。由于知道obj是MyWidget,也可以将它铸造成MyWidget *:MyWidget *myWidget = qobject_cast<MyWidget *>(obj);铸造成
MyWidget成功因为qobject_cast()makes no distinction between built-in Qt types and custom types.QLabel *label = qobject_cast<QLabel *>(obj); // label is 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!")); }虽然可以使用
QObject作为基类不用Q_OBJECT宏及不用元对象代码,信号和槽及在此处描述的其它特征将不可用若Q_OBJECTmacro is not used. From the meta-object system’s point of view, aQObject子类 (没有元代码) 相当于具有元对象代码的其最接近祖先。例如,这意味着className()will not return the actual name of your class, but the class name of this ancestor.因此,强烈推荐所有子类化的
QObject使用Q_OBJECT宏,不管它们是否有实际使用信号,槽及特性。