元对象是什么?
其实就是用来存储类的结构信息的对象;由于其在QT中的名称为QMetaObject所以翻译过来就叫元对象。
那么类的结构信息存储在哪里的呢?
其实类的结构信息存储在一个类型为QMetaObject名为staticMetaObject的全局变量中我们可将其称作元对象。
存储的过程:
1.在Qt中元对象是在编译时由元对象编译器(Meta Object Compiler,即 moc)根据类的源文件生成的。
2.编译器在扫描源文件时,将包含了 QObject 宏的类声明识别出来
3.moc会解析该类的声明、信号、槽和属性等信息,并生成对应的元对象代码,提取类的结构信息,并将其存储在元对象的静态全局变量(staticMetaObject)中
3.生成的元对象代码会与源文件一起被编译形成最终的编译结果
比如编写类MyObject,继承QObject,并声明Q_OBJECT(必须)
#include <QObject>
class MyObject : QObject
{
Q_OBJECT
qint32 tempInt;
bool tempBool;
public:
explicit MyObject(QObject* parent = nullptr);
signals:
void mySignal();
public slots:
void mySlot();
};
#endif // MYOBJECT_H
编译后会生成MOC代码,其中有一个全局静态变量staticMetaObject
QT_INIT_METAOBJECT const QMetaObject MyObject::staticMetaObject = { {
QMetaObject::SuperData::link<QObject::staticMetaObject>(),
qt_meta_stringdata_MyObject.data,
qt_meta_data_MyObject,
qt_static_metacall,
nullptr,
nullptr
} };
这个staticMetaObject就是存储了我们需要的结构信息的元对象
我们可以通过对象的metaObject()函数来获取并访问它
例如:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyObject myobj;
qDebug() << myobj.metaObject()->className();
return a.exec();
}
这个元对象中几乎存储了类的所有结构信息比如:
1.类名和父类名:元对象存储了类的名称以及其直接父类的名称。
2.属性信息:元对象中包含了类的属性的信息,包括属性名称、类型、读写访问权限等。
3.方法信息:元对象存储了类中定义的所有方法的信息,包括名称、参数类型和参数数量等。
5.信号和槽信息:元对象存储了类中定义的所有信号和槽的信息,包括信号和槽的名称、参数类型和参数数量等。
6.元对象连接信息:元对象中存储了类之间的连接信息,表示一个类的信号连接到另一个类的槽的关系。
7.其他元对象相关信息:元对象还可以存储其他相关的元对象信息,如类的静态成员信息和嵌套类型等。
如何访问这些信息
获取类的名称以及父类名称
MyObject myobj;
const QMetaObject* metaObject = myobj.metaObject();
qDebug()<<"类名称:" << metaObject->className();
qDebug()<<"父类名称:" << metaObject->superClass()->className();
获取属性需先将属性在类中进行声明
class MyObject : QObject
{
Q_OBJECT
Q_PROPERTY(qint32 tempInt READ getTempInt WRITE setTempInt)
private:
qint32 tempInt;
bool tempBool;
public:
explicit MyObject(QObject* parent = nullptr);
MyObject(qint32 a,bool isTrue);
qint32 getTempInt() const;
void setTempInt(qint32 t);
signals:
void mySignal();
public slots:
void mySlot();
};
获取类的属性
int propertyCount = metaObject->propertyCount();
qDebug()<<"属性数量:" << propertyCount;
QObject *object = dynamic_cast<QObject*>(&myobj);
for (int i = 0; i < propertyCount; ++i)
{
QMetaProperty property = metaObject->property(i);
qDebug() << "Property name:" << property.name();
qDebug() << "Property type:" << property.typeName();
qDebug() << "Property value:" << property.read(object);
}
想用名称来访问的可先根据名称获取索引,在用索引读取属性值
int index = metaObject->indexOfProperty("tempInt");
方法调用
index = metaObject->indexOfMethod("testSum(int,int)");
QMetaMethod method = metaObject->method(index); // 获取方法
if (method.methodType() == QMetaMethod::Method){
QList<QByteArray> parameterTypes = method.parameterTypes();
QList<QGenericArgument> arguments;
for (const QByteArray& parameterType : parameterTypes) {
if (parameterType == "int") {
int value = 265; // 假设参数为 int 类型
arguments.append(Q_ARG(int, value));
}
qDebug() << "parameterType = " << parameterType;
}
int returnValue = 0;
bool isCall = method.invoke(object,
Qt::AutoConnection,Q_RETURN_ARG(int,returnValue), arguments.value(0), arguments.value(1));
qDebug() << "call " << isCall << " = " << returnValue;
}else {
qDebug() << "methodType = " << method.methodType();