Qt 如何使用反射?

c++ 反射 标准库暂时还没有,那我们来看看如何使用 qt 来进行反射.

反射类的案例

1. 通过注册的类型需找 id 进行实例化该类

myclass.h

#include <QtCore>

class MyClass
{
public:
MyClass() {}
QString name(){
return "cheungxiongwei";
}
};
//声明元对象类型
Q_DECLARE_METATYPE(MyClass)

main.cpp

#include <QCoreApplication>
#include "myclass.h" int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv); // 注册自定义的类
qRegisterMetaType<MyClass>("MyClass"); // 通过静态函数获取注册类的 id,id 不为 0 时,则获取成功.大部分基础类型都可以获取到 id,如 QString QByteArray
int id = QMetaType::type("MyClass");
if(id != 0){
// 根据 id 创建该类型
void *myClass = QMetaType::create(id);
// 转换指针
MyClass *my = static_cast<MyClass*>(myClass);
// 调用函数
qDebug() << my->name(); // 这里可以添加一些自己自己的处理函数 // 释放内存
QMetaType::destroy(id, myClass);
myClass = nullptr;
} return a.exec();
}

2. 通过调用静态成员变量 MyClass::staticMetaObject 获取元对象信息,比较类名称来确定 QMetaObject

myclass.h

class MyClass1 : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE MyClass1() {}
virtual ~MyClass1() {}
// 添加宏 Q_INVOKABLE 可以使用 invokeMethod 调用该函数
Q_INVOKABLE QString name(QString name){
return name.append("xiongwei");
} QString name_(){
return "cheungxiongwei";
}
}; class MyClass2 : public QObject
{
Q_OBJECT
public:
MyClass2() {}
virtual ~MyClass2() {}
}; inline QMetaObject GetMetaObjectByClassName(QString className)
{
QMetaObject metaObject;
if(className.compare("MyClass1") == 0){
metaObject = MyClass1::staticMetaObject;
}else if (className.compare("MyClass2") == 0){
metaObject = MyClass2::staticMetaObject;
} // and so on, you get the idea ... return metaObject;
} inline QMetaObject GetMetaObjectByClassName(QString className)
{
QMetaObject metaObject;
if(className.compare("MyClass1") == 0){
metaObject = LayoutCameraGrab::staticMetaObject;
}else if (className.compare("MyClass2") == 0){
metaObject = LayoutImageRead::staticMetaObject;
} // and so on, you get the idea ... return metaObject;
} inline void printMetaObject(const QMetaObject *metaObject)
{
qDebug() << "Class:" << metaObject->className();
for(int i = 0;i < metaObject->classInfoCount();++i){
qDebug() << "ClassInfo:" << metaObject->classInfo(i).name() << metaObject->classInfo(i).value();
} for(int i = 0;i < metaObject->constructorCount();++i){
qDebug() << "Constructor:" << metaObject->constructor(i).name() << metaObject->constructor(i).parameterNames();
} for(int i = 0;i < metaObject->enumeratorCount();++i){
qDebug() << "Enum:" << metaObject->enumerator(i).name();
} for(int i = 0;i < metaObject->methodCount();++i){
qDebug() << "Method:" << metaObject->method(i).name() << metaObject->method(i).parameterNames() << metaObject->method(i).tag();
} for(int i = 0;i < metaObject->propertyCount();++i){
qDebug() << "Proper:" << metaObject->property(i).name();
}
}

main.cpp

Note that only constructors that are declared with the Q_INVOKABLE modifier are made available through the meta-object system.

上面一句话说的是只有在构造函数前面添加 Q_INVOKABLE 宏后才可以 QMetaObject 的函数 newInstance 创建该实例.

#include <QCoreApplication>
#include "myclass.h" int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv); // 通过类名称获取元对象类型
QMetaObject metaObject = GetMetaObjectByClassName("MyClass1"); // 实例化该类
QObject *object = metaObject.newInstance();
if(object){
QString ret;
// 调用 name 带参数函数
// 如果未加 Q_INVOKABLE 宏,则输出 QMetaObject::invokeMethod: No such method MyClass1::name<QString>
metaObject.invokeMethod(
object,
"name",
Qt::DirectConnection,
Q_RETURN_ARG(QString,ret),
Q_ARG(QString,"cheung"));
// 打印返回值
qDebug() << ret; // 转换指针类型调用未加 Q_INVOKABLE 宏的函数.
MyClass1 *myclass = static_cast<MyClass1*>(object);
Debug() << myclass->name_();
} qDebug() << object; return a.exec();
}

Qt 如何使用反射?的更多相关文章

  1. Qt and C++ Reflection,利用Qt简化C++的反射实现

    如何在C++中实现反射机制,应该算是C++开发中经常遇到的问题之一.C++程序没有完整的元数据,也就无法实现原生的反射机制.从性能的角度讲,这样的设计不难理解,毕竟在运行时储存这些元数据需要额外的开销 ...

  2. Qt 反射

    简介 本文主要讲解Qt是如何实现反射,以及一点点反射使用的小心得. 文章概览 Qt反射内幕小窥 详细内容 反射前期准备 得到注册的类成员变量 得到注册的类成员函数 访问类成员属性(get,set) 调 ...

  3. Qt信号槽连接在有默认形参下的情况思考

    写下这个给自己备忘,比如函数 ) 你在调用端如论是test(3)或者test(),都可以正确调用到这个函数. 但是,如果放到Qt中的信号槽的话,这个还是值得讲一讲的,不然的话,可能会引起相应的误会. ...

  4. Qt核心剖析: moc

    前面我们说过,Qt 不是使用的“标准的” C++ 语言,而是对其进行了一定程度的“扩展”.这里我们从Qt新增加的关键字就可以看出来:signals.slots 或者 emit.所以有人会觉得 Qt 的 ...

  5. Qt编写控件属性设计器1-加载插件

    一.前言 加载插件是整个属性设计器的第一步要打通的功能,插件中的控件都加载不了,后面就别搞别玩下去了没法玩的,要从一个动态库中加载出来控件,肯定需要用到反射机制,以前做.NET开发的时候就觉得反射这个 ...

  6. 《InsideUE4》UObject(二)类型系统概述

    曾子曰:吾日三省吾身--为人谋而不忠乎?与朋友交而不信乎?传不习乎? 引言 上一篇我们谈到了在游戏引擎,或者在程序和高级编程语言中,设计一个统一对象模型得到的好处,和要付出的代价,以及在UE里是怎么对 ...

  7. qmake和moc的功能(★firecat推荐★)

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://devbean.blog.51cto.com/448512/355100 前面我们 ...

  8. QObject 源代码阅读

    我们进入 qt/src 文件夹.你可能对这里的目录名时曾相识,因为几乎这里的所有文件夹名都对应着 Qt 的模块的名字:gui,network,multimedia等等.我们从最核心的 QtCore 开 ...

  9. Qt根据类名创建对象(元对象反射)

    在java语言中,可以使用getObject(String)函数,从类名直接构建新的对象. 而在C++中是没有这种机制的,Qt虽然提供了元对象机制,但只可以获取对象的类名,不能反向构建. 这个问题我在 ...

随机推荐

  1. 如何同步发送put或者delete请求

    1.必须把前端发送方式改为post . 2.在web.xml中配置一个filter:HiddenHttpMethodFilter过滤器 3.必须携带一个键值对,key=_method,  value= ...

  2. 关于conda-新手必读

    一.管理conda 通过anaconda来安装python及python包,让你不必关心系统是否安装了一些依赖,如zlib等等,anaconda已经集成了这些依赖,可以方便的安装python 下载请点 ...

  3. 11.SUSE Linux服务器系统网卡配置重启问题

    问题:系统更改IP地址重启服务时网卡信息不正确 linux#~ vi /etc/sysconfig/network/ifcfg-eth0 BOOTPROTO='static'BROADCAST='19 ...

  4. 2018-10-10-weekly

    Algorithm 字典序排数 What 给定一个整数n,返回从1到n的字典顺序,例如,给定 n =13,返回 [1,10,11,12,13,2,3,4,5,6,7,8,9] ,尽可能的优化算法的时间 ...

  5. django classonlymethod 和 python classmethod的区别

    --classmethod可以被一个实例调用,classonlyethod只能被类调用 class Kls(object): no_inst = 0 def __init__(self): Kls.n ...

  6. 每次当浏览到网页,点击tab标签又回到顶部去了!

    通常tab的标签使用a链接,而a链接的href值为#,这是一个锚点的属性,因此他会跳转到网页的顶端.如果你的tab包含一个id=tab,也可以设置为href="#tab"这样他就会 ...

  7. centos 7 网卡绑定 bond0 开机无法自启

    https://blog.csdn.net/u012881151/article/details/54910847 1.环境CentOS Linux release 7.2.1511 (Core)li ...

  8. web选择文件夹上传

    我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 这次项目的需求: 支持大文件的上传和续传,要求续传支持所有浏览器,包括ie6,ie7,i ...

  9. POJ 1502 MPI MaeIstrom ( 裸最短路 || atoi系统函数 )

    题意 : 给出 N 个点,各个点之间的路径长度用给出的下三角矩阵表示,上上角矩阵和下三角矩阵是一样的,主对角线的元素都是 0 代表自己到达自己不用花费,现在问你从 1 到 N 的最短路,矩阵的 x 代 ...

  10. Nginx负载均衡与反向代理—《亿级流量网站架构核心技术》

    当我们的应用单实例不能支撑用户请求时,此时就需要扩容,从一台服务器扩容到两台.几十台.几百台.然而,用户访问时是通过如http://www.XX.com的方式访问,在请求时,浏览器首先会查询DNS服务 ...