反射

-在计算机科学中,反射是指计算机程序在运行时(Run time)可以访问、检测和修改它本身状态或行为的一种能力。[1]用比喻来说,反射就是程序在运行的时候能够“观察”并且修改自己的行为。

要注意术语“反射”和“内省”(type introspection)的关系。内省(或称“自省”)机制仅指程序在运行时对自身信息(称为元数据)的检测;反射机制不仅包括要能在运行时对程序自身信息进行检测,还要求程序能进一步根据这些信息改变程序状态或结构。

C++的反射

C++的标准语法是不提供反射的特性的,不过随着C++17的定稿,估计这个关键词不会加到标准中了。不过这个我们可以用template来实现,这次就不写template了。今天主要是讲的是Qt。

Qt的反射

Qt最大的特点就是增加了moc的过程,个人理解,Qt扩展了C++的语法,以及增强了自己的基本库。

Meta Object System is a part of Qt framework core provided to support Qt extensions to C++ like signals/slots for inter-object communication, run-time type information, and the dynamic property system.[1]
Architecture
The Meta object system consists of 3 things: QObject class, Q_OBJECT macro and a tool called moc (Meta-Object Compiler). QObject is the base class for all Qt classes, Q_OBJECT macro is used to enable meta-object features in classes and finally moc is a preprocessor that changes Q_OBJECT macro instances to C++ source code to enable meta object system mechanism in the class in which it is used.[2]
Using the meta object system has brought some criticism. In Qt documentation, several reasons have been given for the use of the meta object system, including benefits of code generation, dynamism of GUIs, automatic binding to scripting languages, not adding limitations and also reasonable performance in signal/slot implementation with moc.[3] There are some efforts to make Qt needless of a preprocessor. These efforts include re-implementing Qt moc using libclang.[4]

moc可以理解将Qt中的一些关键词,比如Q_Object ,Q_PROPERTY等转化为c++的基本语法,所以我们在编译Qt的工程时,首先要qmake->make。

个人认为Qt有两个我比较看重的特点。

  • STL基础库的扩展。
  • C++基本语法与特性的扩展。

尤其是基本语法的扩展,比如信号槽,元对象系统,让C++一个静态语言有了动态语言的特性(当然你也可以用template来实现,但是这玩意儿一般人又用不起,而且写起来也比较恶心)。这一点我就可以吹爆了。

下边开始讲Qt的反射。Qt的反射是基于Qt的元对象系统的。当然Qt还不能做到像java那样通过类名来创建一个对象,这个需要我们自己写一个工厂模式。个人认为,除了这一点,与java中的反射没有啥区别了。都可以动态的去访问其成员变量,成员函数,以及设置属性。当然必须加上Qt自己的语法。

举个栗子

  1. //1 .继承 QObject
  2. class TestObject : public QObject
  3. {
  4. Q_OBJECT // 2.声明Q_OBJECT
  5. Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChange) //3. Q_PROPERTY 注册成员变量
  6. Q_PROPERTY(QString text MEMBER m_text NOTIFY textChange) //4. 注册的成员变量能够响应自定义的signals textChange
  7. public:
  8. TestObject(QObject* parent);
  9. ~TestObject();
  10. void init();
  11. //------
  12. Q_INVOKABLE QString text(); //5.注册类的成员函数
  13. Q_INVOKABLE void setText(const QString& strText); //5.注册类的成员函数
  14. QString m_text; //类的成员变量
  15. signals:
  16. void textChange(); //自定义的signals
  17. public slots:
  18. void textslot(){qDebug()<<"textslot"<<endl;} //自定义的signals响应的槽函数
  19. };
  20. //cpp
  21. TestObject::TestObject(QObject* parent) : QObject (parent)
  22. {
  23. this->setObjectName("TestObject");
  24. connect(this, SIGNAL(textChange()),this, SLOT(textslot()));
  25. }
  26. TestObject::~TestObject()
  27. {
  28. }
  29. void TestObject::init()
  30. {
  31. qDebug()<<"*********************"<<endl;
  32. qDebug()<<"init"<<endl;
  33. }
  34. QString TestObject::text()
  35. {
  36. return m_text;
  37. }
  38. void TestObject::setText(const QString& strText)
  39. {
  40. if (m_text == strText)
  41. return;
  42. m_text = strText;
  43. // emit textChange(); //有了第四条这个语句已经不需要了。
  44. }

这里看调用方法

  1. TestObject* obj = new TestObject(this); // new一个对象
  2. qDebug()<<obj->objectName()<<endl; //输出对象的名字
  3. // custom object property
  4. obj->setProperty("text", "hahaha"); //设置对象的属性
  5. qDebug()<<obj->property("text").toString()<<endl; //输出对象的属性
  6. //得到注册的类成员函数
  7. qDebug()<<"begin--------------------custom class method"<<endl;
  8. const QMetaObject* mobj = obj->metaObject();
  9. qDebug()<<mobj->methodCount()<<endl;
  10. for(int i = 0; i < mobj->methodCount(); i++)
  11. {
  12. QMetaMethod mMethod = mobj->method(i);
  13. QByteArray byteArray = mMethod.name();
  14. //输出函数类型与函数名称
  15. qDebug()<<mMethod.typeName()<<"->"<<QString(byteArray)<<endl;
  16. }
  17. qDebug()<<"end----------------------custom class method"<<endl;
  18. //调用注册的成员函数,通过Q_RETURN_ARG来获取返回值
  19. qDebug()<<"begin QMetaObject::invokeMethod"<<endl;
  20. QString invokeString;
  21. //调用类的成员函数
  22. QMetaObject::invokeMethod(obj, "text", Qt::DirectConnection, Q_RETURN_ARG(QString, invokeString));
  23. qDebug()<<invokeString<<endl;
  24. qDebug()<<"end QMetaObject::invokeMethod"<<endl;
  25. // 再次设置text值,可以响应这个信号,可以参考4
  26. obj->setProperty("text", "luelueluelue");

看上边的代码,C++能够随时获取当前类的成员变量与成员函数以及调用。(并不是通过C++的type id)这就是反射。反射在写GUI的时候是非常有用的。也就是我们可以随时获取当前对象的任何我们想要的属性以及想要调用的函数。静态语言有了动态语言的特性。这就是Qt强大的地方。

Qt通过类名来实现真正的反射

  1. #include <QByteArray>
  2. #include <QMetaObject>
  3. #include <QHash>
  4. #ifndef OBJECTFACTORY_H
  5. #define OBJECTFACTORY_H
  6. class ObjectFactory
  7. {
  8. public:
  9. template<typename T>
  10. static void registerClass()
  11. {
  12. constructors().insert( T::staticMetaObject.className(), &constructorHelper<T> );
  13. }
  14. static QObject* createObject( const QByteArray& className, QObject* parent = NULL )
  15. {
  16. Constructor constructor = constructors().value( className );
  17. if ( constructor == NULL )
  18. return NULL;
  19. return (*constructor)( parent );
  20. }
  21. private:
  22. typedef QObject* (*Constructor)( QObject* parent );
  23. template<typename T>
  24. static QObject* constructorHelper( QObject* parent )
  25. {
  26. return new T( parent );
  27. }
  28. static QHash<QByteArray, Constructor>& constructors()
  29. {
  30. static QHash<QByteArray, Constructor> instance;
  31. return instance;
  32. }
  33. };
  34. #endif // OBJECTFACTORY_H

下边是使用方法。todo ,这个东西应该写成单例模式的。

  1. //使用方法
  2. ObjectFactory fac;
  3. fac.registerClass<TestObject>();
  4. qDebug()<<"begin-------------------------------"<<endl;
  5. TestObject* object = qobject_cast<TestObject*>(fac.createObject( "TestObject" , this));
  6. object->setText("template factory");
  7. qDebug()<<object->text()<<endl;

http://www.cryfeifei.cn/395.html

Qt元对象(Meta-Object)系统与反射的更多相关文章

  1. Qt元对象和属性系统详解

    Qt 是一个用标准 C++ 编写的跨平台开发类库,它对标准 C++ 进行了扩展,引入了元对象系统.信号与槽.属性等特性,使应用程序的开发变得更高效. 本节将介绍 Qt 的这些核心特点,对于理解和编写高 ...

  2. Qt 元对象系统(Meta-Object System)(不管是否使用信号槽,都推荐使用)

    Qt 元对象系统(Meta-Object System) Qt的元对象系统基于如下三件事情: 类:QObject,为所有需要利用原对象系统的对象提供了一个基类. 宏:Q_OBJECT,通常可以声明在类 ...

  3. Qt元对象系统简介

    在Qt中提供了c++的扩展,提供了一种元对象系统的机制,(meta-object-system)的机制.其中包含了信号与槽的内部机制,能够访问到QObject子类的元对象信息的功能. Q_OBJECT ...

  4. 解析Qt元对象系统(五) Q_INVOKABLE与invokeMethod(automatic connection从Qt4.8开始的解释已经与之前不同,发送对象驻足于哪一个线程并不重要,起到决定作用的是接收者对象所驻足的线程以及发射信号(该信号与接受者连接)的线程是不是在同一个线程)good

    概述查看Qt源码可知,Q_INVOKABLE是个空宏,目的在于让moc识别. 使用Q_INVOKABLE来修饰成员函数,目的在于被修饰的成员函数能够被元对象系统所唤起. Q_INVOKABLE与QMe ...

  5. Qt 元对象系统(Meta-Object System)

    (转自:http://blog.csdn.net/aladdina/article/details/5496891) Qt的元对象系统基于如下三件事情: 类:QObject,为所有需要利用原对象系统的 ...

  6. 解析Qt元对象系统(四) 属性系统(确实比较方便)

    官方解释 我们在Qt源码中可以看到一个QObject的子类经常会用到一些Q_开头的宏,例如QMainWindow类开始部分代码是这样的: Q_PROPERTY(QSize iconSize READ ...

  7. qt 元对象系统

    元对象系统 Qt中的元对象系统是用来处理对象间通讯的信号/槽机制.运行时的类型信息和 动态属性系统. 它基于下列三类: QObject类: 类声明中的私有段中的Q_OBJECT宏: 元对象编译器(mo ...

  8. Qt——元对象和属性机制

    http://www.cnblogs.com/hellovenus/p/5582521.html 一.元对象 元对象(meta object)意思是描述另一个对象结构的对象,比如获得一个对象有多少成员 ...

  9. Qt笔记——元对象系统

    Qt元对象系统提供了对象间的通信机制:信号和槽.以及执行类形信息和动态属性系统的支持.是标注C++的一个扩展,它使得Qt可以更好的实现GUI图形用户界面编程.Qt的元对象系统不支持C++模板.虽然模板 ...

随机推荐

  1. i春秋——“百度杯”CTF比赛 十月场——Login

    根据页面源码提示的 test1 test1 登录 刷新此页面并抓包,有个show=0值得关注 在发送的包的header中加一句show:1,即可得到member.php的源码 <?php inc ...

  2. 【转载】Gradle学习 第八章:依赖管理基础

    转载地址:http://ask.android-studio.org/?/article/10 This chapter introduces some of the basics of depend ...

  3. HBase安装指南

    一.事前准备 此安装是建立在hadoop集群运行起来的基础上,此hadoop版本为2.6.0,其他版本未测试,可能存在兼容性问题. 上传所需文件到/usr/local/soft   二.zookeep ...

  4. 【前端_React】Node.js和webpack的安装

    第一步——安装Node.js 首先要安装Node.js,Node.js自带了软件包管理工具npm,可以使用npm安装各种插件.Node.js的下载地址 可以自定义安装到指定的路径下,待安装完成后命令行 ...

  5. 使用aptitude安装软件

    linux的版本依赖问题很令人纠结,不过我们可以通过使用aptitude软件包管理器来解决这个依赖问题,aptitude是可以选择合适的版本与匹配软件安装.

  6. Jupyter-notebook安装问题及解决

    两种方式: 1.pip install jupyter notebook 2.安装Anaconda 1.pip安装 通过命令行pip,要注意是在哪个虚拟环境,安装好后jupyter notebook所 ...

  7. 转载-mysql中文编码问题

    具体原理见:MySQL:windows中困扰着我们的中文乱码问题 分割线: 我的电脑win7 64位,这个问题可能是所有win系统出现的问题 我出现的问题: 是正确的 出现了中文的张三,则错误,编码错 ...

  8. ESA2GJK1DH1K微信小程序篇: 小程序连接MQTT简单的Demo

    前言 这节让大家知道小程序是怎么连接的MQTT 其实,小程序就是网页实现MQTT 使用的是下面这个包 新建一个工程 一,把包放到util里面 二,编写连接函数 三,调用连接函数 订阅主题显示接收的消息 ...

  9. CSS3实现PS中的蚁行线动画以及画布的马赛克背景图

    话不多说,先看例子,外链 效果截图如下: 蚁行线 马赛克背景 代码: 蚁行线代码如下: /* <!-- HTML代码 --> <div class="ant"&g ...

  10. jupyterlab数据处理

    目录 jupyterlab: jupyterlab简介: jupyterlab特点: jupyterlab安装,启动 使用jupyterlab: 设置jupyterlab jupyterlab: ju ...