Qt’s meta-object system provides the signals and slots mechanism for inter-object communication, run-time type information, and the dynamic property system.
Qt元对象系统提供内建对象通信的信号和槽机制,运行时类信息,和动态属性系统。
The meta-object system is based on three things:
元对象系统基于三样东西:
1.The QObject class provides a base class for objects that can take advantage of the meta-object system.
1.QObject类是对象的基类,可以利用元对象系统的优势。
2.The Q_OBJECT macro inside the private section of the class declaration is used to enable meta-object features, such as dynamic properties, signals, and slots.
Q_OBJECT宏在类的私有区声明,用来使用元对象的功能,例如:动态属性,信号和槽。
3.The Meta-Object Compiler (moc) supplies each QObject subclass with the necessary code to implement meta-object features.
元对象编译器(moc)为每个QObject子类提供必要的代码,使得其实现元对象的功能。
The moc tool reads a C++ source file. If it finds one or more class declarations that contain the Q_OBJECT macro, it produces another C++ source file which contains the meta-object code for each of those classes. This generated source file is either #include'd into the class's source file or, more usually, compiled and linked with the class's implementation
moc工具读取C++源文件。如果它发现一个或多个包含Q_OBJECT宏的类声明,它将为那些类产生一个包含了元对象代码的C++源文件。生成的文件包含d(#include'd,什么鬼)至类的源文件,还有,类的实现的编译和链接。
In addition to providing the signals and slots mechanism for communication between objects (the main reason for introducing the system), the meta-object code provides the following additional features:
除了为对象间提供信号和槽通信机制外(介绍系统的主要原因),元对象代码还提供以下额外功能:
QObject::metaObject() returns the associated meta-object for the class.
QObject::metaObject()返回类的相关联元对象。
QMetaObject::className() returns the class name as a string at run-time, without requiring native run-time type information (RTTI) support through the C++ compiler.
QMetaObject::className()在运行时返回字符串类名,无需本地运行时类信息(RTTI)支持C++编译器。
QObject::inherits() function returns whether an object is an instance of a class that inherits a specified class within the QObject inheritance tree.
QObject::inherits()函数返回一个对象是否是在QObject继承树中指定类的派生类的实例。
QObject::tr() and QObject::trUtf8() translate strings for internationalization.
QObject::tr()和QObject::trUtf8()翻译字符串以实现国际化。
QObject::setProperty() and QObject::property() dynamically set and get properties by name.
QObject::setProperty()和QObject::property()通过名字动态地设置和获得属性。
QMetaObject::newInstance() constructs a new instance of the class.
QMetaObject::newInstance()构造类的新实例。
It is also possible to perform dynamic casts using qobject_cast() on QObject classes. The 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), or 0 if the object's type is incompatible.
另外也可以使用qobject_cast()执行QObject类之间的动态转换。qobject_cast()函数的行为类似标准C++的 dynamic_cast(),优势是它无需RTTI的支持并且可以跨动态库工作。它视图将参数转换成括号中指定类型的指针,如果对象是正确类型(在运行时确定的)返回非0指针,如果对象类型不符,返回0。
For example, let's assume MyWidget inherits from QWidget and is declared with the Q_OBJECT macro:
例如,让我们假设MyWidget继承于QWidget并且使用Q_OBJECT宏声明:
QObject *obj = new MyWidget;
The obj variable, of type QObject *, actually refers to a MyWidget object, so we can cast it appropriately:
变量obj是QObject类型指针,实际上它指向MyWidget对象,所以我们可以适当转换它:
QWidget *widget = qobject_cast<QWidget *>(obj);
The cast from QObject to QWidget is successful, because the object is actually a MyWidget, which is a subclass of QWidget. Since we know that obj is a MyWidget, we can also cast it to MyWidget *:
从QObject到QWidget的转换是成功的,因为对象实际是MyWidget(QWidget的子类)。因为我们知道对象MyWidget,所以我们可以将它转换成MyWidget*:
MyWidget *myWidget = qobject_cast<MyWidget *>(obj);
The cast to MyWidget is successful because qobject_cast() makes no distinction between built-in Qt types and custom types.
转换成MyWidget是成功的,因为qobject_cast()使内置的Qt类型和自定义类型之间没有区别。
QLabel *label = qobject_cast<QLabel *>(obj);
//label is 0
The cast to QLabel, on the other hand, fails. The pointer is then set to 0. This makes it possible to handle objects of different types differently at run-time, based on the type:
另外转换成QLabel失败,指针会被设置为0。这使得可能在运行时以不同的方式处理不同类型的对象,基于类型:
if(QLabel* label = qobject_cast<QLabel*>(obj))
{
label->setText(tr("Ping"));
}
else if(QPushButton* button = qobject_cast<QPushButton*>(obj))
{
button->setText(tr("Poing!"));
}
While it is possible to use QObject as a base class without the Q_OBJECT macro and without meta-object code, neither signals and slots nor the other features described here will be available if the Q_OBJECT macro is not used. From the meta-object system's point of view, a QObject subclass without meta code is equivalent to its closest ancestor with meta-object code. This means for example, that QMetaObject::className() will not return the actual name of your class, but the class name of this ancestor.
尽管可以使用无Q_OBJECT声明和无元对象代码的QObject类作为基类,但如果不使用Q_OBJECT宏信号和槽不可使用,这里描述的其他功能也不能使用。从元对象系统的角度看,一个QObject子类没有元代码就相当于它最近的有元对象代码的祖先。这就意味着,例如:QMetaObject::className()不会返回类的实际的名字而是祖先的类名。
Therefore, we strongly recommend that all subclasses of QObject use the Q_OBJECT macro regardless of whether or not they actually use signals, slots, and properties.
所以我们强烈建议所有的QObject的子类中使用Q_OBJECT宏而不管它实际是否使用信号,槽和属性。