相对于Java天生的这一特性, C++并不具备;但进入到Qt领域,这一切都变得简单自如了。

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

■ QObject::metaObject()

返回关联的元对象

■ QObject::className()

在运行时状态下返回类名

■ QObject::inherits()

判断类的继承关系

■ QObject::tr()

QObject::trUtf8()

提供国际化,翻译字符串

■ QObject::setProperty()

QObject::property()

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

■ QObject::newInstance()

创建实例

其中QObject::className()、QObject::setProperty()和QObject::property()比较吸引眼球,这正是反射机制中的基本功能。建立在Qt的元对象系统的基础上,只要拥有元对象(QMetaObject)的类就支持反射!如何拥有元对象?方法很简单:只需继承于QObject或者它的子类(多重继承的话,QObject类应该放在第一个),在头文件的结构声明中写上Q_OBJECT即可!

元对象信息

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

■ QMetaClassInfo

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

■ QMetaEnum

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

■ QMetaMethod

提供类成员函数的元数据

■ QMetaProperty

提供类成员属性的元数据

根据QMetaObject提供的数据对象,完全可以编写通用的代码来支持反射特性。

例子:

声明一个类,继承于QObject

classReflectionObject : publicQObject

{

Q_OBJECT

Q_PROPERTY(intId READ Id WRITE setId)

Q_PROPERTY(QString Name READ Name WRITEsetName)

Q_PROPERTY(QString Address READ Address WRITEsetAddress)

Q_PROPERTY(PriorityType Level READ Priority WRITEsetPriority)

Q_ENUMS(PriorityType)

public:

enumPriorityType { High, Low, VeryHigh,VeryLow };

Q_INVOKABLEint Id() {returnm_Id; }

Q_INVOKABLEQString Name() { returnm_Name; }

Q_INVOKABLEQString Address() { returnm_Address; }

Q_INVOKABLEPriorityType Priority() const {returnm_Priority; }

Q_INVOKABLEvoid setId(constint& id) {m_Id = id; }

Q_INVOKABLEvoid setName(constQString& name) {m_Name = name; }

Q_INVOKABLEvoid setAddress(constQString& address) {m_Address = address; }

Q_INVOKABLEvoid setPriority(PriorityType priority) {m_Priority = priority; }

private:

int         m_Id;

QString  m_Name;

QString  m_Address;

PriorityTypem_Priority;

};

为了能检测到类成员函数,得在函数前加上一个宏Q_INVOKABLE, 这意味着该函数在元对象系统编译该类时注册该函数,则在运行过程中能被元对象调用。

经过上述声明,在运行时即可做些操作:

/*遍历该类的成员: */

ReflectionObjecttheObject;

constQMetaObject*theMetaObject =theObject.metaObject();

intmetathodIndex;

intmetathodCount = theMetaObject->methodCount();

for(metathodIndex = 0; metathodIndex < metathodCount; ++metathodIndex)

{

QMetaMethodoneMethod =theMetaObject->method(metathodIndex);

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

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

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

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

}

/*遍历该类的属性: */

intpropertyIndex;

intpropertyCount = theMetaObject->propertyCount();

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

{

QMetaPropertyoneProperty =theMetaObject->property(propertyIndex);

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

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

}

/*遍历该类的枚举集合*/

intenumeratorIndex;

intenumeratorCount = theMetaObject->enumeratorCount();

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

{

QMetaEnumoneEnumerator =theMetaObject->enumerator(enumeratorIndex);

intenumIndex;

intenumCount = oneEnumerator.keyCount();

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

{

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

}

}

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

通过这个测试能将ReflectionObject这个类的方法和属性完全遍历出来,完成自身的检查,也即反射。

反射在Qt应用程序中的用途

在Qt的元对象系统支持下,赋予了C++并不直接拥有的此特性。这样加大了开发应用程序的自由度,尤其在软件工程中强调高内聚低耦合的状态下。

具体的用例中, 可以通过Qt Designer这个工具来描述(尽管暂不清楚内部是否利用此方法来实现J):

对于其中的控件,放入到Designer中时,Designer事先并不知道(其实也不需要知道)放入插件的类型、方法和属性。将插件导入时,它可以检测该控件的类型、方法和属性;

这样在Designer中绘制控件时,遍历该控件的属性, 将这些属性显示在属性窗口中,便于修改;

在信号/槽对话框编辑时,遍历该控件的属性,提取信号/槽函数,放入对应的编辑区域里;

http://blog.csdn.net/playstudy/article/details/7861329

深入Qt 学习 -- 反射机制(比较简单清楚)的更多相关文章

  1. (转)java反射机制及简单工厂模式

    第一步,定义一个接口类 package factory.face; /** * 接口,为了保证返回的对象可以统一用 Product接受 * @author Administrator */ publi ...

  2. java反射机制的简单介绍

    参考博客: https://blog.csdn.net/mlc1218559742/article/details/52754310 先给出反射机制中常用的几个方法: Class.forName (& ...

  3. 045-利用反射机制,简单的实现PHP插件模式

    <?php //利用反射机制,简单的实现PHP插件模式 # 假设,我们有一款开源产品,所有开发者都必须在我定制的需求之上,进行二次开发, # 而开发完成后的新模块,就是一个不一样的新插件,可以放 ...

  4. Java反射机制的简单学习

    今天看了一下Java的反射机制,就此记录一下. 首先,我们要先了解一下什么是反射? 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力. JAV ...

  5. Qt类反射机制

    前言   如何通过类名动态的创建对象(类反射),对于Java开发者来说一点也不陌生,当然Qt也提供了一个元对象系统(The Meta-Object System),通过这个系统我们可以动态的在运行时获 ...

  6. 利用Java反射机制优化简单工厂设计模式

    之前项目有个需求,审批流程的时候要根据配置发送信息:发送短信.发送邮件.当时看到这个就想到要用工厂模式,为什么要用工厂模式呢?用工厂模式进行大型项目的开发,可以很好的进行项目并行开发.就是一个程序员和 ...

  7. C++ 反射机制的简单实现

    C++并不支持反射机制,只能自己实现. 如果需要实现字字符串到函数到映射,一定要使用到函数指针. 简单实现反射机制,根据字符串来构造相应到类.主要有以下几点: (1) 可以使用map保存字符从到函数指 ...

  8. Java反射机制的简单应用

    一直感觉java的反射机制非常强大,可是可用的地方不多.在android学习的时候.一直想实现挂断电话的功能,可是系统并没有提供开放的api接口,看了一下网上使用反射机制来实现该功能,确实非常强大,非 ...

  9. java学习——反射机制

    /* * JAVA反射机制是在运行状态中,对于任意一个类 (class文件),都能够知道这个类的所有属性和方法: * 对于任意一个对象,都能够调用它的任意一个方法和属性: * 这种动态获取的信息以及动 ...

随机推荐

  1. 10.3、android输入系统_必备Linux编程知识_任意进程双向通信(scoketpair+binder)

    3. 任意进程间通信(socketpair_binder) 进程每执行一次open打开文件,都会在内核中有一个file结构体表示它: 对每一个进程在内核中都会有一个task_struct表示进程,这个 ...

  2. 6、修改应用程序数码相框以支持自动关闭LCD

    1. 修改数码相框以自动关闭LCD关闭LCD : 在读取触摸屏的函数中判断:如果15S内无数据,执行: echo auto > /sys/devices/platform/mylcd/power ...

  3. Win7下多线程中OpenFileDialog和SaveFileDialog失效的解决办法(转载)

    在程序中,通常会使用独立线程来操作OpenFileDialog或者SaveFileDialog控件,但是在某些情况下(Win7系统下)调用 ShowDialog方法并不显示选择路径对话框.此时需要对启 ...

  4. 目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。静态库是一个或者多个obj文件的打包

    前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”) ...

  5. 微信小程序 富文本插件 循环渲染方式

    感谢GitHub https://github.com/icindy/wxParse/wiki/wxParse%E5%A4%9A%E6%95%B0%E6%8D%AE%E5%BE%AA%E7%8E%AF ...

  6. [JS Compose] 1. Refactor imperative code to a single composed expression using Box

    After understanding how Box is, then we are going to see how to use Box to refacotr code, to un-nest ...

  7. php实现包含min函数的栈(这个题目用另外一个栈做单调栈的话时间复杂度会低很多)

    php实现包含min函数的栈(这个题目用另外一个栈做单调栈的话时间复杂度会低很多) 一.总结 这个题目用另外一个栈做单调栈的话时间复杂度会低很多 二.php实现包含min函数的栈 题目描述 定义栈的数 ...

  8. UE4的JSON读写方式<一>

    声明:所有权利保留. 转载必须说明出处:http://blog.csdn.net/cartzhang/article/details/41009343 UE4的Json的解析博客地址: http:// ...

  9. ios开发事件处理之 四:hittest方法的底层实现与应用

    #import "XMGWindow.h" /** 1:注意点:hitTest方法内部会调用pointInside方法,询问触摸点是否在自己身上,当遍历子控件时,传入的坐标点要进行 ...

  10. Java验证是否为纯数字

    package rbq.codedemo; import java.util.regex.Pattern; /** * Created by rbq on 2016/12/13. */ public ...