在Q_OBJECT的代码中,QMetaObject是一个很重要的角色,字面意思就称为元对象吧,有道词典的解释
可以看看Qt助手的解释
The QMetaObject class contains meta-information about Qt objects.
QMetaObject类包含关于Qt对象的元信息。
The Qt Meta-Object System in Qt is responsible for the signals and slots inter-object communication mechanism, runtime type information, and the Qt property system. A single QMetaObject instance is created for each QObject subclass that is used in an application, and this instance stores all the meta-information for the QObject subclass. This object is available as QObject::metaObject().
Qt中的Qt元对象系统负责信号和插槽的对象间通信机制、运行时类型信息和Qt属性系统。为应用程序中使用的每个QObject子类创建一个QMetaObject实例,该实例存储QObject子类的所有元信息。这个对象可以作为QObject::metaObject()使用。
This class is not normally required for application programming, but it is useful if you write meta-applications, such as scripting engines or GUI builders.
这个类通常不是应用程序编程所需要的,但是如果您编写元应用程序(例如脚本引擎或GUI构建器),它就非常有用。
The functions you are most likely to find useful are these:
- className() returns the name of a class.
- superClass() returns the superclass's meta-object.
- method() and methodCount() provide information about a class's meta-methods (signals, slots and other invokable member functions).
- enumerator() and enumeratorCount() and provide information about a class's enumerators.
- propertyCount() and property() provide information about a class's properties.
- constructor() and constructorCount() provide information about a class's meta-constructors.
The index functions indexOfConstructor(), indexOfMethod(), indexOfEnumerator(), and indexOfProperty() map names of constructors, member functions, enumerators, or properties to indexes in the meta-object. For example, Qt uses indexOfMethod() internally when you connect a signal to a slot.
索引函数indexOfConstructor()、indexOfMethod()、indexOfEnumerator()和indexOfProperty()将构造函数、成员函数、枚举器或属性的名称映射到元对象中的索引。例如,当您将信号连接到插槽时,Qt在内部使用indexOfMethod()。
Classes can also have a list of name--value pairs of additional class information, stored in QMetaClassInfo objects. The number of pairs is returned by classInfoCount(), single pairs are returned by classInfo(), and you can search for pairs with indexOfClassInfo().
类还可以有一个名称—附加类信息的值对列表,存储在QMetaClassInfo对象中。对的数量由classInfoCount()返回,单个对由classInfo()返回,您可以使用indexOfClassInfo()搜索对。
Note: Operations that use the meta object system are generally thread- safe, as QMetaObjects are typically static read-only instances generated at compile time. However, if meta objects are dynamically modified by the application (for instance, when using QQmlPropertyMap), then the application has to explicitly synchronize access to the respective meta object.
注意:使用元对象系统的操作通常是线程安全的,因为QMetaObjects通常是在编译时生成的静态只读实例。但是,如果应用程序动态地修改了元对象(例如,在使用QQmlPropertyMap时),则应用程序必须显式地同步对相应元对象的访问。
可以在代码中测试,根据第二段翻译,为应用程序中使用的每个QObject子类创建一个QMetaObject实例,该实例存储QObject子类的所有元信息。这个对象可以作为QObject::metaObject()使用。
参看Q_OBJECT宏的代码可知:
#define Q_OBJECT \
public: \
QT_WARNING_PUSH \
Q_OBJECT_NO_OVERRIDE_WARNING \
static const QMetaObject staticMetaObject; \
virtual const QMetaObject *metaObject() const; \
virtual void *qt_metacast(const char *); \
virtual int qt_metacall(QMetaObject::Call, int, void **); \
QT_TR_FUNCTIONS \
private: \
Q_OBJECT_NO_ATTRIBUTES_WARNING \
Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
QT_WARNING_POP \
struct QPrivateSignal {}; \
QT_ANNOTATE_CLASS(qt_qobject, "")
我们可以直接使用staticMetaObject来调用QMetaObject的相关信息
qDebug() ::type
invokeMethod(QObject *context, Func function,
Qt::ConnectionType type = Qt::AutoConnection,
typename QtPrivate::FunctionPointer::ReturnType *ret = nullptr)
{
return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn(function), type, ret);
}
template
static typename std::enable_if::IsPointerToMemberFunction
&& !std::is_convertible::value
&& QtPrivate::FunctionPointer::ArgumentCount == 0, bool>::type
invokeMethod(QObject *context, Func function,
typename QtPrivate::FunctionPointer::ReturnType *ret)
{
return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn(function), Qt::AutoConnection, ret);
}
// invokeMethod() for Functor
template
static typename std::enable_if::IsPointerToMemberFunction
&& QtPrivate::FunctionPointer::ArgumentCount == -1
&& !std::is_convertible::value, bool>::type
invokeMethod(QObject *context, Func function,
Qt::ConnectionType type = Qt::AutoConnection, decltype(function()) *ret = nullptr)
{
return invokeMethodImpl(context,
new QtPrivate::QFunctorSlotObjectWithNoArgs(std::move(function)),
type,
ret);
}
template
static typename std::enable_if::IsPointerToMemberFunction
&& QtPrivate::FunctionPointer::ArgumentCount == -1
&& !std::is_convertible::value, bool>::type
invokeMethod(QObject *context, Func function, typename std::result_of::type *ret)
{
return invokeMethodImpl(context,
new QtPrivate::QFunctorSlotObjectWithNoArgs(std::move(function)),
Qt::AutoConnection,
ret);
}
#endif
QObject *newInstance(QGenericArgument val0 = QGenericArgument(nullptr),
QGenericArgument val1 = QGenericArgument(),
QGenericArgument val2 = QGenericArgument(),
QGenericArgument val3 = QGenericArgument(),
QGenericArgument val4 = QGenericArgument(),
QGenericArgument val5 = QGenericArgument(),
QGenericArgument val6 = QGenericArgument(),
QGenericArgument val7 = QGenericArgument(),
QGenericArgument val8 = QGenericArgument(),
QGenericArgument val9 = QGenericArgument()) const;
enum Call {
InvokeMetaMethod,
ReadProperty,
WriteProperty,
ResetProperty,
QueryPropertyDesignable,
QueryPropertyScriptable,
QueryPropertyStored,
QueryPropertyEditable,
QueryPropertyUser,
CreateInstance,
IndexOfMethod,
RegisterPropertyMetaType,
RegisterMethodArgumentMetaType
};
int static_metacall(Call, int, void **) const;
static int metacall(QObject *, Call, int, void **);
struct { // private data
const QMetaObject *superdata;
const QByteArrayData *stringdata;
const uint *data;
typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **);
StaticMetacallFunction static_metacall;
const QMetaObject * const *relatedMetaObjects;
void *extradata; //reserved for future use
} d;
private:
static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret);
};