Qt反射機制實現(xiàn),通過類名創(chuàng)建對象

Qt反射機制實現(xiàn),通過類名創(chuàng)建對象的圖1

版權(quán)聲明:本文為知乎作者「Qt開發(fā)編程」的原創(chuàng)文章,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

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

概述

首先說一下什么是反射:
反射是指程序在運行時動態(tài)獲取對象屬性與方法的一種機制,即編譯器需要將類型信息(屬性類型與偏移地址以及成員函數(shù)的地址等信息)編譯到程序文件中,當(dāng)程序運行時將這些信息加載到內(nèi)存中去,做到運行時只根據(jù)對象的地址或引用就可以獲取到對象的類型信息,從而利用這些信息達(dá)到修改或重建對象的目標(biāo)。
再簡單一點說,就是可以通過類名稱來創(chuàng)建一個類對象,這在Java和Object-C中是原生支持的,所以實現(xiàn)起來非常簡單,但是C++就不支持了,如果想要用到反射機制,那就得自己實現(xiàn)。

反射的作用

在計算機編程語言中,反射機制可以用來:
  1. 獲取類型的信息,包括屬性、方法
  2. 動態(tài)調(diào)用方法
  3. 動態(tài)構(gòu)造對象
  4. 從程序集中獲得類型

反射的缺點

性能:反射可以理解成是一種解釋操作,這個過程總是要慢于直接調(diào)用的。當(dāng)然,性能問題的程度是可以控制的,如果程序在很少涉及的地方使用,性能將不會是一個問題。適用于性能不敏感的部分。
反射模糊了程序內(nèi)部實際發(fā)生的事情,會比直接代碼更加復(fù)雜。增加了理解代碼的難度。
缺點不能掩飾其優(yōu)點,針對不同的場景使用合理的技術(shù)才是最高境界。

反射的使用場景

序列化(Serialization), in custom binary format or in XML, JSON, XDR, etc.
反序列化(Deseriallization),從序列中重建了對象實例與關(guān)系。
遠(yuǎn)程方法調(diào)用, remote procedure calls (RPC) / remote method invocation (RMI)。
對象/關(guān)系數(shù)據(jù)映射(O/R mapping)eg. Hibernate,作為虛擬對象數(shù)據(jù)庫,實現(xiàn)數(shù)據(jù)和對象的持久化。
數(shù)據(jù)綁定(Data Binding),實現(xiàn)數(shù)據(jù)對象與關(guān)系的可視化,與交互控制調(diào)整。
某些軟件設(shè)計模式的自動化和半自動化實現(xiàn)。

如何實現(xiàn)

其實實現(xiàn)也不難的,在創(chuàng)建對象之前,需要先將要類注冊,注冊的目的是為了將類名及函數(shù)指針做個綁定,采用Hash表來實現(xiàn),創(chuàng)建對象的時候,直接從hash表中取出函數(shù)指針并創(chuàng)建對象即可。
由于我們使用Qt對象來實現(xiàn),那取類名可以直接用元對象系統(tǒng)的staticMetaObject.className()來獲取。
話不多說,直接上代碼:
#include <QObject>
template<typename L> //用于反射傳父類參數(shù)class CReflectClass{public: //首先要注冊創(chuàng)建的類 template<typename T> static void registerClass(){ //&constructorHelper<T>其實是獲取創(chuàng)建的函數(shù)指針,核心功能。 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);//執(zhí)行new T函數(shù),創(chuàng)建對應(yīng)實例 }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; }};
測試調(diào)用
#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>();
//創(chuàng)建對象 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__;}



深圳市優(yōu)飛迪科技有限公司成立于2010年,是一家專注于產(chǎn)品開發(fā)平臺解決方案與物聯(lián)網(wǎng)技術(shù)開發(fā)的國家級高新技術(shù)企業(yè)。

十多年來,優(yōu)飛迪科技在數(shù)字孿生、工業(yè)軟件尤其仿真技術(shù)、物聯(lián)網(wǎng)技術(shù)開發(fā)等領(lǐng)域積累了豐富的經(jīng)驗,并在這些領(lǐng)域擁有數(shù)十項獨立自主的知識產(chǎn)權(quán)。同時,優(yōu)飛迪科技也與國際和國內(nèi)的主要頭部工業(yè)軟件廠商建立了戰(zhàn)略合作關(guān)系,能夠為客戶提供完整的產(chǎn)品開發(fā)平臺解決方案。

優(yōu)飛迪科技技術(shù)團隊實力雄厚,主要成員均來自于國內(nèi)外頂尖學(xué)府、并在相關(guān)領(lǐng)域有豐富的工作經(jīng)驗,能為客戶提供“全心U+端到端服務(wù)”。

Qt反射機制實現(xiàn),通過類名創(chuàng)建對象的圖2

登錄后免費查看全文
立即登錄
App下載
技術(shù)鄰APP
工程師必備
  • 項目客服
  • 培訓(xùn)客服
  • 平臺客服

TOP