Qt5之反射机制(内省)

摘要:
}Q_ INVOKABBLEvoisetAddress(constQString&address){m_address=address;}private;intm_Id;QStringm_名称;QStringm_地址;优先级类型_优先级;方法(methodIndex);“签名;

Qt的元对象系统除了提供信号/槽机制的特性之外,它还提供了以下特性:

QObject::metaObject()

返回关联的元对象

QMetaObject::className()

在运行时状态下返回类名

QObject::inherits()

判断类的继承关系

QObject::tr(),QObject::trUtf8()

提供国际化,翻译字符串

QObject::setProperty(),QObject::property()

通过名称来动态设置和获取属性

QMetaObject::newInstance()

创建新实例

通过QObject::metaObject()方法, 所有继承于QObject的类可以 返回元对象系统为其生成的metaObject对象。QMetaObject提供的一些重要信息:

QMetaClassInfo

通过宏Q_CLASSINFO的支持,提供类的附加信息

QMetaEnum

Qt特色的枚举对象,支持key和 value之间的互转

QMetaMethod

提供类成员函数的元数据

QMetaProperty

提供类成员属性的元数据

Qt反射前期准备

1、首先得继承于Q_Object,同时需要在class中加入Q_OBJECT。

2、注册类成员变量需要使用Q_PROPERTY

  Q_PROPERTY( type member READ get WRITE set) 其中READ,WRITE是关键字

  Type表示成员的类型(不支持自定义类型,对Qt很多基本类型都支持);

  Member代表你给该成员另外起的名字,可以和变量名不同;get,set就是自己在C++函数里面定义的基本的访问函数名,不需要写参数。

3、注册类成员函数

  如果你希望这个函数能够被反射,那么很简单,只需要在类的函数声明前加入Q_INVOKABLE关键字。

下面是一个例子

//声明一个继承于QObject的类
class ReflectionObject : public QObject

{
      Q_OBJECT

      Q_PROPERTY(int Id READ Id WRITE setId)

      Q_PROPERTY(QString Name READ Name WRITE setName)

      Q_PROPERTY(QString Address READ Address WRITE setAddress)

      Q_PROPERTY(PriorityType Priority READ Priority WRITE setPriority)

      Q_ENUMS(PriorityType)

public:

      enum PriorityType  {High,Low,VeryHigh,VeryLow};

      Q_INVOKABLE int Id() {return m_Id; }

      Q_INVOKABLE QString Name() { return m_Name; }

      Q_INVOKABLE QString Address() { return m_Address; }

      Q_INVOKABLE PriorityType Priority() const {return m_Priority; }

      Q_INVOKABLE void setId(const int & id) {m_Id = id; }

      Q_INVOKABLE void setName(const QString & name) {m_Name = name; }

      Q_INVOKABLE void setAddress(const QString & address) {m_Address = address; }

      Q_INVOKABLE void setPriority(PriorityType priority) {m_Priority = priority; }

private:
      int      m_Id;

      QString  m_Name;

      QString  m_Address;

      PriorityType m_Priority;

};

 

遍历该类的成员函数:

ReflectionObject theObject;

const QMetaObject* theMetaObject =theObject.metaObject();

int methodIndex;

int methodCount = theMetaObject->methodCount();

for(methodIndex = 0; methodIndex < methodCount; ++methodIndex)

{

      QMetaMethod oneMethod =theMetaObject->method(methodIndex);

      qDebug() <<"typeName: " <<oneMethod.typeName();

      qDebug() <<"signature: " <<oneMethod.signature();

      qDebug() <<"methodType: " <<oneMethod.methodType();;

      qDebug() <<"parameterNames: " <<oneMethod.parameterNames() <<"
";

}

  其中typeName代表返回类型,signature只的是函数的原貌,methodType代表函数的类型,在Qt中分为三类(槽,信号,普通函数),parameterNames代表函数参数

遍历该类的成员变量:

int propertyIndex;

int propertyCount = theMetaObject->propertyCount();

for(propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex)

{

      QMetaProperty oneProperty =theMetaObject->property(propertyIndex);

      qDebug() <<"name: " << oneProperty.name();

      qDebug() <<"type: " <<oneProperty.type() <<"
";

}

遍历该类的枚举集合:

int enumeratorIndex;

int enumeratorCount = theMetaObject->enumeratorCount();

for(enumeratorIndex = 0; enumeratorIndex < enumeratorCount; ++enumeratorIndex)

{

      QMetaEnum oneEnumerator =theMetaObject->enumerator(enumeratorIndex);

      int enumIndex;

      int enumCount = oneEnumerator.keyCount();

      for(enumIndex = 0;enumIndex < enumCount; ++enumIndex)

      {

             qDebug() <<oneEnumerator.key(enumIndex) <<" ==> " <<oneEnumerator.value(enumIndex);

      }

}

  这里我们看到QMetaEnum存在key、value配对出现,这必然可以互转,而QMetaEnum确实提供了方式:valueToKey()、keyToValue()。

反射的应用

  反射反射,就我目前的认知水平来看,通过使用字符串,来实现函数的通用化调用,例如你可以利用反射把很多函数放置到数组中,实现一次遍历,全部调用。

  目前见到的大多是利用反射来操作数据库,例如hibernate,其实可以利用Qt的反射,快速实现所谓的hibernate。

至此,Qt自带的反射功能已经罗列完整。但是Qt自身并没有提供类反射机制,就是像Java那样通过getObject(String)函数,从类型直接构建新的对象。实现类反射机制请阅读下一篇博客。

 http://www.cnblogs.com/RainyBear/p/5251482.html

  参考资料:http://blog.csdn.net/playstudy/article/details/7861329

免责声明:文章转载自《Qt5之反射机制(内省)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇cocos2dx 精灵(如子弹)的去除el-upload 上传表单验证下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C++静态库中使用_declspec(dllexport) 不能导出函数的问题

在某项目中,有一些静态库,这些静态库中有类型命名的函数GET_XXX。在一次项目结构调整的时候,我想将调用这静态库的代码编译成DLL,并且将这些Get函数导出,我就直接就这些函数前面添加了_declspec(dllexport), 然后代码结构就成为: 静态库A: 包括很多 _declspec(dllexport) GET_XXX 函数。 动态库B:未直接...

QOS-CBQ概述

 QOS-CBQ概述    2018年7月7日    19:56 CBQ(基于类的对列)是一种基于QOS policy实现的拥塞管理技术。 CBQ中包含一个LLQ(低延迟队列),用来支撑EF(快速转发)类业务被绝对优先发送,保证延迟。 CBQ中最大包含64个BQ(带宽保证队列),用来支撑AF(确保转发)类业务,保证每一个队列的带宽及可控的延迟。 CBQ...

VxWorks函数栈帧剖析

VxWorks任务内存地址空间布局 VxWorks系统中,所有Tasks(包括系统任务和用户任务)都工作在特权模式,共享所有内存。A任务可以直接访问B任务的内存地址空间而不会触发任何“异常”。下图为单个任务的内存地址空间布局,任务ID(Task ID)分割任务控制块(TCB)和任务栈,任务栈中压栈函数栈帧,从高地址向低地址增长。 首先,我们查看任务列表...

cocos2D-X从的源代码的分析cocos2D-X学习OpenGL(1)----cocos2D-X渲染架构

        个人原创。欢迎转载,转载请注明原文地址http://blog.csdn.net/bill_man         从本篇文章開始,将分析cocos2D-X 3.0源码,第一部分是从cocos2D-X学习OpenGL,也就是分析cocos2D-X 3.0的渲染代码,本篇首先介绍cocos2D-X 3.0的渲染结构。使用的是3.0正式版。...

实战二(上):程序出错该返回啥?NULL、异常、错误码、空对象?

我们可以把函数的运行结果分为两类。一类是预期的结果,也就是函数在正常情况下输出的结果。一类是非预期的结果,也就是函数在异常(或叫出错)情况下输出的结果。比如,在上一节课中,获取本机名的函数,在正常情况下,函数返回字符串格式的本机名;在异常情况下,获取本机名失败,函数返回 UnknownHostException 异常对象。 在正常情况下,函数返回数据的类...

[转]【C/C++】Linux下使用system()函数一定要谨慎

曾经的曾经,被system()函数折磨过,之所以这样,是因为对system()函数了解不够深入。只是简单的知道用这个函数执行一个系统命令,这远远不够,它的返回值、它所执行命令的返回值以及命令执行失败原因如何定位,这才是重点。当初因为这个函数风险较多,故抛弃不用,改用其他的方法。这里先不说我用了什么方法,这里必须要搞懂system()函数,因为还是有很多人用...