在上一篇中,我们将的是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
版权声明:本文为博主原创文章,转载请附上博文链接!

QMetaMethod 获取成员函数的元信息的更多相关文章

  1. Python基础之给函数增加元信息

    1. 参数注解 当写好一个函数以后,想为这个函数的参数添加一些额外的信息,这样的话,其他的使用者就可以清楚的知道这个函数应该怎么使用,这个时候可以使用函数参数注解. 函数参数注解能提示程序员应该怎样正 ...

  2. 通过DatabaseMetaData数据库元信息类,获取特定数据库的元信息

    数据库版本:mysql8.0.18 ide:idea 2019.3 可以看到代码中连接的数据库为course_select,是一个学生的选课系统的数据库 然后通过DatabaseMetaData的ge ...

  3. Java反射理解(四)-- 获取成员变量构造函数信息

    Java反射理解(四)-- 获取成员变量构造函数信息 步骤 获取成员变量信息: obj.getClass() 获取类类型对象 成员变量也是对象,java.lang.reflect.Field 类中封装 ...

  4. 从汇编看c++成员函数指针(三)

    前面的从汇编看c++中成员函数指针(一)和从汇编看c++成员函数指针(二)讨论的要么是单一类,要么是普通的多重继承,没有讨论虚拟继承,下面就来看一看,当引入虚拟继承之后,成员函数指针会有什么变化. 下 ...

  5. C++ 指向类成员函数指针的用法(转自维基百科)

    类成员函数指针 类成员函数指针(member function pointer),是C++语言的一类指针数据类型,用于存储一个指定类具有给定的形参列表与返回值类型的成员函数的访问信息. 目录 1 语法 ...

  6. QMetaEnum获取枚举元信息

    QMetaEnum 类提供了一个枚举的元数据.我们可以使用该类的静态模板函数,fromType<enumerator>来获得关于某个枚举的QMetaEnum对象,然后就可以调用该类的成员函 ...

  7. java反射获取类的成员函数,成员变量,构造函数

    package com.imooc.reflect;import javax.sound.midi.Soundbank;import java.lang.reflect.Constructor;imp ...

  8. 实现php获取mp3文件元信息如播放时间歌曲作者等

    最近收集到一个php获取mp3文件元信息的类,感觉比较方便.现在分享给大家! 下面是使用方式和测试方式: <?php include_once 'mp3file.class.php'; func ...

  9. 微信企业号-根据code获取成员信息(过期code)

    二次请求获取成员信息时,会报如下错误: { "errcode": "40029", "errmsg": "invalid code ...

随机推荐

  1. Integer面试连环炮以及源码分析(转)

    场景:   昨天有位朋友去面试,我问他面试问了哪些问题,其中问了Integer相关的问题,以下就是面试官问的问题,还有一些是我对此做了扩展. 问:两个new Integer 128相等吗? 答:不.因 ...

  2. Wireshark过滤命令总结

    1.表达式1 (tcp.flags.reset == )&&(tcp.seq == ) 2.表达式2 (tcp.flags.syn == )&&(tcp.analysi ...

  3. Leetcode: Sum of Two Integers && Summary: Bit Manipulation

    Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -. Exam ...

  4. php接口数据安全解决方案(一)

    前言 目录介绍 登录鉴权图 接口请求安全性校验整体流程图 代码展示 演示用户登录 演示获取用户信息 文章完整代码地址 后记 前言 目的: 1.实现前后端代码分离,分布式部署 2.利用token替代se ...

  5. nginx指定允许的IP访问

    接下来我们将tomcat.i4t.com 也就是10.4.82.140进行配置权限 #只允许10.4.82.142访问 cat /usr/local/nginx/conf/nginx.conf use ...

  6. CentOS7下搭建zabbix监控(三)——Zabbix监控服务配置

    CentOS7下搭建zabbix监控(一)——Zabbix监控端配置 CentOS7下搭建zabbix监控(二)——Zabbix被监控端配置 (1).配置Zabbix监控Apache服务 主机名:yo ...

  7. dts reader

    package com.aliyun.dts.connect; import com.alibaba.fastjson.JSONObject; import com.aliyun.drc.client ...

  8. springboot配置虚拟路径访问用户上传的附件及图片资源

    在springmvc项目中,我们通常把图片及附件存放到WEB-INF/upload类似的路径. springboot项目是通过jar包方式运行的. 笔者曾尝试以下代码,把图片转成base64格式的图片 ...

  9. Tips for TMUX

    常用命令 tmux ls # 显示后台session列表 tmux new -t [name] # 新建session tmux a -t [name] # 进入session tmux kill-s ...

  10. 微信小程序之对象转化为数组

    对象转成数组方式一(数组里面是一个个number类型的元素) let dictObject= { , , , , }; // 对象转成数组方式一 var createArr = [] for (let ...