Qt反射机制实现,通过类名创建对象

Qt反射机制实现,通过类名创建对象的图1

版权声明:本文为知乎作者「Qt开发编程」的原创文章,转载请附上原文出处链接及本声明。

原文链接:https://zhuanlan.zhihu.com/p/615027308

概述

首先说一下什么是反射:
反射是指程序在运行时动态获取对象属性与方法的一种机制,即编译器需要将类型信息(属性类型与偏移地址以及成员函数的地址等信息)编译到程序文件中,当程序运行时将这些信息加载到内存中去,做到运行时只根据对象的地址或引用就可以获取到对象的类型信息,从而利用这些信息达到修改或重建对象的目标。
再简单一点说,就是可以通过类名称来创建一个类对象,这在Java和Object-C中是原生支持的,所以实现起来非常简单,但是C++就不支持了,如果想要用到反射机制,那就得自己实现。

反射的作用

在计算机编程语言中,反射机制可以用来:
  1. 获取类型的信息,包括属性、方法
  2. 动态调用方法
  3. 动态构造对象
  4. 从程序集中获得类型

反射的缺点

性能:反射可以理解成是一种解释操作,这个过程总是要慢于直接调用的。当然,性能问题的程度是可以控制的,如果程序在很少涉及的地方使用,性能将不会是一个问题。适用于性能不敏感的部分。
反射模糊了程序内部实际发生的事情,会比直接代码更加复杂。增加了理解代码的难度。
缺点不能掩饰其优点,针对不同的场景使用合理的技术才是最高境界。

反射的使用场景

序列化(Serialization), in custom binary format or in XML, JSON, XDR, etc.
反序列化(Deseriallization),从序列中重建了对象实例与关系。
远程方法调用, remote procedure calls (RPC) / remote method invocation (RMI)。
对象/关系数据映射(O/R mapping)eg. Hibernate,作为虚拟对象数据库,实现数据和对象的持久化。
数据绑定(Data Binding),实现数据对象与关系的可视化,与交互控制调整。
某些软件设计模式的自动化和半自动化实现。

如何实现

其实实现也不难的,在创建对象之前,需要先将要类注册,注册的目的是为了将类名及函数指针做个绑定,采用Hash表来实现,创建对象的时候,直接从hash表中取出函数指针并创建对象即可。
由于我们使用Qt对象来实现,那取类名可以直接用元对象系统的staticMetaObject.className()来获取。
话不多说,直接上代码:
#include <QObject>
template<typename L> //用于反射传父类参数class CReflectClass{public: //首先要注册创建的类 template<typename T> static void registerClass(){ //&constructorHelper<T>其实是获取创建的函数指针,核心功能。 constructors().insert(T::staticMetaObject.className(), &constructorHelper<T>); } static QObject *createObject(const QByteArray& className,L* parent = nullptr){ Constructor constructor = constructors().value(className); if (constructor == nullptr ){ return nullptr; } return (*constructor)(parent);//执行new T函数,创建对应实例 }private: typedef QObject *(*Constructor)(L* parent); template<typename T> static QObject *constructorHelper(L* parent){ if(parent) return new T(parent); else { return new T(); } } static QHash<QByteArray, Constructor> &constructors() { static QHash<QByteArray, Constructor> instance; return instance; }};
测试调用
#include "widget.h"#include "ui_widget.h"#include "creflectclass.h"
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget){ ui->setupUi(this);
//注册类 CReflectClass<Widget>::registerClass<ClassA>(); CReflectClass<Widget>::registerClass<ClassB>();
//创建对象 auto a = static_cast<ClassA*>(CReflectClass<Widget>::createObject("ClassA",this)); a->test(); auto b = CReflectClass<Widget>::createObject("ClassB",this);}
Widget::~Widget(){ delete ui;}
ClassB::ClassB(QObject *parent): QObject(parent){ qDebug() << __FUNCTION__ ;}
ClassA::ClassA(QObject *parent): QObject(parent) { qDebug() << __FUNCTION__ ;}
void ClassA::test(){ qDebug() << __FUNCTION__;}



深圳市优飞迪科技有限公司成立于2010年,是一家专注于产品开发平台解决方案与物联网技术开发的国家级高新技术企业。

十多年来,优飞迪科技在数字孪生、工业软件尤其仿真技术、物联网技术开发等领域积累了丰富的经验,并在这些领域拥有数十项独立自主的知识产权。同时,优飞迪科技也与国际和国内的主要头部工业软件厂商建立了战略合作关系,能够为客户提供完整的产品开发平台解决方案。

优飞迪科技技术团队实力雄厚,主要成员均来自于国内外顶尖学府、并在相关领域有丰富的工作经验,能为客户提供“全心U+端到端服务”。

Qt反射机制实现,通过类名创建对象的图2

默认 最新
当前暂无评论,小编等你评论哦!
点赞 评论 收藏
关注