Qt 反射
简介
本文主要讲解Qt是如何实现反射,以及一点点反射使用的小心得。
文章概览
Qt反射内幕小窥
详细内容
反射前期准备
得到注册的类成员变量
得到注册的类成员函数
访问类成员属性(get,set)
调用注册的函数
反射应用
总结
Qt反射内幕小窥
Qt反射机制是基于moc(meta object compiler)实现的,在这里多插一句(可以说Qt所有C++没有的特性,几乎都和这个有关系)。但是需要注意的是Qt提供的反射式基本的反射,不支持类的反射,这个与Java,C#还是有差别的。
moc讲解
通常C++的编译过程为
预处理->编译->链接->运行
Qt编译的过程中,有一个moc的过程,在Qt工程构建过程中的qmake其实就是干这个事的。moc->预处理->编译->链接->运行。
在moc过程中,需要处理的事情如下:
1、 识别一些特殊的宏Q_OBJECT、Q_PROPERTY、Q_INVOKABLE。。。; 如果碰到这些关键字,Qt自然就会去生成对应的moc文件。
2、 slot,signal自然也是如此。
3、 uidesigner,同样也是在这个阶段处理的;
详细内容
反射前期准备
1、 首先得继承于Q_Object,同时需要在class中加入Q_OBJECT,但是Q_Object的构造函数默认是私有的不让继承。
在类中直接使用Q_GADGET也可以实现反射,。。。据说只能实现部分功能,目前我只实现到能遍历成员属性,函数,但是不能访问其中的值。
这个过程其实就是定义QMetaObject的过程,具体见Qt源码
2、 注册类成员变量需要使用Q_PROPERTY
Q_PROPERTY( type member READ get WRITE set) 其中READ,WRITE是关键字
Type表示成员的类型(不支持自定义类型,对Qt很多基本类型都支持);
Member代表你给该成员另外起的名字,可以和变量名不同;get,set就是自己在C++函数里面定义的基本的访问函数名,不需要写参数。直接上代码:
3、 注册类成员函数
如果你希望这个函数能够被反射,那么很简单,只需要在类的函数声明前加入Q_INVOKABLE关键字。
例如Q_INVOKABLE int func( QString flag );
#include <QObject>
class MyClass : public QObject
{
Q_OBJECT
Q_PROPERTY(int Member1 READ Member1 WRITE setMember1 )
Q_PROPERTY(int Member2 READ Member2 WRITE setMember2 )
Q_PROPERTY(QString MEMBER3 READ Member3 WRITE setMember3 )
public:
explicit MyClass(QObject *parent = );
signals:
public slots:
public:
Q_INVOKABLE int Member1();
Q_INVOKABLE int Member2();
Q_INVOKABLE QString Member3();
Q_INVOKABLE void setMember1( int mem1 );
Q_INVOKABLE void setMember2( int mem2 );
Q_INVOKABLE void setMember3( const QString& mem3 );
Q_INVOKABLE int func( QString flag );
private:
int m_member1;
int m_member2;
QString m_member3;
};
得到注册的类成员变量
MyClass theObj;
const QMetaObject* metaObj = theObj.metaObject();
//1.遍历类的属性
int propertyCnt = metaObj->propertyCount();
for ( int i = ; i < propertyCnt; ++ i )
{
QMetaProperty oneProperty = metaObj->property( i );
cout << " name: " << oneProperty.name();
cout << " type: " << QVariant::typeToName( oneProperty.type()) << "\n";
}
主要思路就是得到其元对象,得到其元属性,然后就能得到你需要的信息,具体的访问函数有name,type,需要注意的是得到的type是枚举值,还在Qt提供了typeToName的函数,你可以得到想要的(例如不是空洞的2,而是”int”)。
得到注册的类成员函数
//2.遍历类的函数成员
int methodCnt = metaObj->methodCount();
for ( int idx = ; idx < methodCnt; ++ idx )
{
QMetaMethod oneMethod = metaObj->method( idx );
cout << "--------begin-------" << "\n";
cout << " typeName: " << oneMethod.typeName() << "\n";
cout << " signature: " << oneMethod.signature() << "\n";
cout << " methodType: " << oneMethod.methodType() << "\n";
cout << "--------end---------" << "\n";
}
和遍历类属性一致,其实就是根据元对象,得到元函数;
其中typeName代表返回类型,signature只的是函数的原貌,methodType代表函数的类型,在Qt中分为三类(槽,信号,普通函数)。
访问类成员属性(get,set)
//3.使用反射
cout << "-------test property-----------" << "\n";
MyClass newObj;
newObj.setProperty("Member1", );
cout << newObj.property( "Member1" ).toString().toStdString() << "\n";
cout << newObj.Member1() << "\n";
cout << "--------end----------" << "\n";
在这里使用的是QObject的property() 和setProperty方法,来访问成员信息。但是对于使用Q_GADGET宏的类,是不能使用这个方法的,还在寻找解决方法,基本思路当然是重写。
调用注册的函数
int ret;
MyClass newObj;
newObj.setMember1( );
newObj.setMember2( );
QMetaObject::invokeMethod( &newObj, "func", Qt::DirectConnection, Q_RETURN_ARG(int, ret ),Q_ARG(QString, "+"));
//普通函数的调用
在MyClass中,我们定义了int func( QString flag ); 这个函数,利用反射的调用方式如上,主要是理解invokeMethod的用法,其中Qt::DirectConnection是函数的执行方式,分为(异步和同步),Q_RETURN_ARG是返回参数,Q_ARG是传入参数,需要按函数声明中参数的顺序依次传入,Qt最多支持9个参数,对于一般的应用没有问题。还有疑问,请移步具见Qt强大的帮助文档。
反射的应用
反射反射,就我目前的认知水平来看,通过使用字符串,来实现函数的通用化调用,例如你可以利用反射把很多函数放置到数组中,实现一次遍历,全部调用。
目前我见到的大多是利用反射来操作数据库,例如hibernate,其实可以利用Qt的反射,快速实现所谓的hibernate,(最近自己独立实现了一套,很方便)。
总结
这篇文章主要讲了如何使用Qt来实现反射,在实用角度上来讲,我们不需要了解Qt是怎么实现反射的,对于怎么用上面说的很清楚了。
转自:http://www.cppblog.com/Cunch/archive/2013/07/13/201779.html
Qt 反射的更多相关文章
- Qt 反射,moc,Q_INVOKABLE
使用Q_INVOKABLE来修饰成员函数,目的在于被修饰的成员函数能够被元对象系统所唤起 Q_INVOKABLE与QMetaObject::invokeMethod均由元对象系统唤起.这一机制在Qt ...
- Qt编写自定义控件属性设计器
以前做.NET开发中,.NET直接就集成了属性设计器,VS不愧是宇宙第一IDE,你能够想到的都给你封装好了,用起来不要太爽!因为项目需要自从全面转Qt开发已经6年有余,在工业控制领域,有一些应用场景需 ...
- Qt编写控件属性设计器1-加载插件
一.前言 加载插件是整个属性设计器的第一步要打通的功能,插件中的控件都加载不了,后面就别搞别玩下去了没法玩的,要从一个动态库中加载出来控件,肯定需要用到反射机制,以前做.NET开发的时候就觉得反射这个 ...
- Qt5之反射机制(内省)
Qt的元对象系统除了提供信号/槽机制的特性之外,它还提供了以下特性: QObject::metaObject() 返回关联的元对象 QMetaObject::className() 在运行时状态下返回 ...
- QT5 QSS QML界面美化视频课程系列 QT原理 项目实战 C++1X STL
QT5 QSS QML界面美化视频课程系列 QT原理 项目实战 C++1X STL 课程1 C语言程序设计高级实用速成课程 基础+进阶+自学 课程2 C语言程序设计Windows GDI图形绘 ...
- Qt and C++ Reflection,利用Qt简化C++的反射实现
如何在C++中实现反射机制,应该算是C++开发中经常遇到的问题之一.C++程序没有完整的元数据,也就无法实现原生的反射机制.从性能的角度讲,这样的设计不难理解,毕竟在运行时储存这些元数据需要额外的开销 ...
- Qt根据类名创建对象(元对象反射)
在java语言中,可以使用getObject(String)函数,从类名直接构建新的对象. 而在C++中是没有这种机制的,Qt虽然提供了元对象机制,但只可以获取对象的类名,不能反向构建. 这个问题我在 ...
- Qt类反射机制
前言 如何通过类名动态的创建对象(类反射),对于Java开发者来说一点也不陌生,当然Qt也提供了一个元对象系统(The Meta-Object System),通过这个系统我们可以动态的在运行时获 ...
- 深入Qt 学习 -- 反射机制(比较简单清楚)
相对于Java天生的这一特性, C++并不具备;但进入到Qt领域,这一切都变得简单自如了. 从Qt的元对象系统可知,除了提供信号/槽机制的特性之外,它还提供了以下特性: ■ QObject::meta ...
随机推荐
- 使用fork并发处理多个client的请求和对等通信p2p
一.在前面讲过的回射客户/服务器程序中,服务器只能处理一个客户端的请求,如何同时服务多个客户端呢?在未讲到select/poll/epoll等高级IO之前,比较老土的办法是使用fork来实现.网络服务 ...
- AVL平衡二叉搜索树原理及各项操作编程实现
C语言版 #include<stdio.h> #include "fatal.h" struct AvlNode; typedef struct AvlNode *Po ...
- RichTextBox指定全部文字显示不同颜色及部分文字高亮颜色显示
指定全部显示不同颜色: public void SetTextContent(string text, ColorEnum color) { Font font = , FontStyle.Bold) ...
- vue开发环境搭建win10
需要安装nodejs, webpack@2.2.1, babel-cli, vue-cli 1 安装nodejs 现在版本默认会安装nodejs 和 npm包 和 配置环境 2 检查是否安装成功,在 ...
- ecshop中ajax的调用
1.首先ecshop是如何定义ajax对象的. ecshop中的ajax对象是在js/transport.js文件中定义的.里面是ajax对象文件.声明了一个var Ajax = Transport; ...
- [sql]MySQL数据备份小结
一 MySQL备份恢复总结: 1,备份所有库 2,分库备份 3,备份某库中的某表 4,备份某库中的多个表 5,分表备份 6,只备份表结构 7,只备份数据 二 MySQL备份恢复参数总结: -A 备份所 ...
- 【Android】3.12 兴趣点( POI)搜索功能
分类:C#.Android.VS2015.百度地图应用: 创建日期:2016-02-04 一.简介 POI(Point of Interest),中文可以翻译为“兴趣点”.在地理信息系统中,一个POI ...
- android笔记---AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="ht ...
- 收集Cocos2d提供的字体!共57种
很多游戏中,便于开发就会直接采用Cocos2d提供的字体库来使用,但是因为提供的种类很多,那么Himi利用一些时间整理了57种字体样式,这些我想足够你用了: 不多说下面一起来看看吧:(每张图对应11种 ...
- ny14 会场安排问题
会场安排问题 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 学校的小礼堂每天都会有许多活动,有时间这些活动的计划时间会发生冲突,需要选择出一些活动进行举办.小刘的工 ...