QMetaMethod 获取成员函数的元信息

在上一篇中,我们将的是QMetaEnum类,它可以获得一个类中由Q_ENUM宏或Q_FLAG宏声明的枚举类型的元信息。同样,QMetaMethod类是用来获取成员方法的元信息的一个类。通过该类,我们可以获取到一个成员方法的类型,比如它是信号、槽、方法、还是构造函数;也可以获得方法的完整签名,以及方法所接受的参数类型和参数名字,当然也可以获取方法的返回值类型;还可以使用access()方法获取成员函数的访问权限。当然,最重要的还是invoke()方法,使用该方法我们可以在任意的QObject对象上调用成员函数。

而要得到一个QMetaMethod类的实例,有如下方法。对于信号,可以使用该类的静态方法fromSignal()来获得相对于该信号的QMetaMethod对象;对于普通成员函数和槽函数,可以使用类的QMetaObject对象来间接获取。分别举例如下:

方法一

QMetaMethod destroyedSignal = QMetaMethod::fromSignal(&QObject::destroyed);
方法二
QString retVal;
QByteArray normalizedSignature = QMetaObject::normalizedSignature("compute(QString, int, double)");
int methodIndex = obj->metaObject()->indexOfMethod(normalizedSignature);
QMetaMethod method = obj->metaObject()->method(methodIndex);
method.invoke(obj,
Qt::DirectConnection,
Q_RETURN_ARG(QString, retVal),
Q_ARG(QString, "sqrt"),
Q_ARG(int, 42),
Q_ARG(double, 9.7));
其中,要使用QMetaObject::normalizedSignature()来规范化函数签名,确保方法签名是invoke()所期望的。

下面,我们以一个实例来使用一下该类:

新建一个Qt控制台程序,再新建一个QObject的子类,在该类中声明一个槽函数。代码如下:

#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <QObject>

class MyObject : public QObject
{
Q_OBJECT
public:
explicit MyObject(QObject *parent = 0);

public slots:
int add(int a, int b);
};

#endif // MYOBJECT_H


然后,在main函数中,我们打印出add槽函数的元信息。代码如下:
#include <QCoreApplication>
#include <QMetaMethod>
#include <QDebug>
#include "myobject.h"

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

MyObject obj;
QByteArray normalizedSignature = QMetaObject::normalizedSignature("add(int, int)");
int methodIndex = obj.metaObject()->indexOfMethod(normalizedSignature);
QMetaMethod metaMethod = obj.metaObject()->method(methodIndex);
qDebug() << "Access: " << metaMethod.access();
qDebug() << "Valid: " << metaMethod.isValid();
qDebug() << "Index: " << metaMethod.methodIndex();
qDebug() << "Signature: " << metaMethod.methodSignature();
qDebug() << "Type: " << metaMethod.methodType();
qDebug() << "Name: " << metaMethod.name();
qDebug() << "Parameter names: " << metaMethod.parameterNames();
qDebug() << "Parameter types: " << metaMethod.parameterTypes();
qDebug() << "Return type: " << metaMethod.returnType();
qDebug() << "Type name: " << metaMethod.typeName();

return a.exec();
}

运行结果如下:

可以结合QMetaMethod中相关的枚举类型定义来理解上面的输出。

enum Access { Private, Protected, Public }
enum MethodType { Method, Signal, Slot, Constructor }


即,该方法的访问权限为public,类型是slot,其他的都很好理解了。
当然,上面说了,我们可以使用该类的invoke()函数,在已有的对象上,调用该函数。代码如下:

int result = 0;
bool bCall = metaMethod.invoke(&obj, Q_RETURN_ARG(int, result), Q_ARG(int, 1), Q_ARG(int, 1));
if(bCall)
{
qDebug() << "1 + 1 = " << result;
}

大家可以自行测试一下结果。

---------------------
作者:求道玉
来源:CSDN
原文:https://blog.csdn.net/Amnes1a/article/details/69220916
版权声明:本文为博主原创文章,转载请附上博文链接!

原文地址:https://www.cnblogs.com/findumars/p/11161019.html