反射

-在计算机科学中,反射是指计算机程序在运行时(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 .继承 QObject
class TestObject : public QObject
{
Q_OBJECT // 2.声明Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChange) //3. Q_PROPERTY 注册成员变量
Q_PROPERTY(QString text MEMBER m_text NOTIFY textChange) //4. 注册的成员变量能够响应自定义的signals textChange
public:
TestObject(QObject* parent);
~TestObject();
void init();
//------
Q_INVOKABLE QString text(); //5.注册类的成员函数
Q_INVOKABLE void setText(const QString& strText); //5.注册类的成员函数
QString m_text; //类的成员变量
signals:
void textChange(); //自定义的signals
public slots:
void textslot(){qDebug()<<"textslot"<<endl;} //自定义的signals响应的槽函数
}; //cpp
TestObject::TestObject(QObject* parent) : QObject (parent)
{
this->setObjectName("TestObject");
connect(this, SIGNAL(textChange()),this, SLOT(textslot()));
}
TestObject::~TestObject()
{
}
void TestObject::init()
{
qDebug()<<"*********************"<<endl;
qDebug()<<"init"<<endl;
}
QString TestObject::text()
{
return m_text;
}
void TestObject::setText(const QString& strText)
{
if (m_text == strText)
return;
m_text = strText;
// emit textChange(); //有了第四条这个语句已经不需要了。
}

这里看调用方法

    TestObject* obj = new TestObject(this);  // new一个对象

    qDebug()<<obj->objectName()<<endl; //输出对象的名字
// custom object property
obj->setProperty("text", "hahaha"); //设置对象的属性
qDebug()<<obj->property("text").toString()<<endl; //输出对象的属性 //得到注册的类成员函数
qDebug()<<"begin--------------------custom class method"<<endl;
const QMetaObject* mobj = obj->metaObject(); qDebug()<<mobj->methodCount()<<endl;
for(int i = 0; i < mobj->methodCount(); i++)
{
QMetaMethod mMethod = mobj->method(i);
QByteArray byteArray = mMethod.name();
//输出函数类型与函数名称
qDebug()<<mMethod.typeName()<<"->"<<QString(byteArray)<<endl;
}
qDebug()<<"end----------------------custom class method"<<endl; //调用注册的成员函数,通过Q_RETURN_ARG来获取返回值
qDebug()<<"begin QMetaObject::invokeMethod"<<endl;
QString invokeString;
//调用类的成员函数
QMetaObject::invokeMethod(obj, "text", Qt::DirectConnection, Q_RETURN_ARG(QString, invokeString));
qDebug()<<invokeString<<endl;
qDebug()<<"end QMetaObject::invokeMethod"<<endl; // 再次设置text值,可以响应这个信号,可以参考4
obj->setProperty("text", "luelueluelue");

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

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

#include <QByteArray>
#include <QMetaObject>
#include <QHash> #ifndef OBJECTFACTORY_H
#define OBJECTFACTORY_H class ObjectFactory
{
public:
template<typename T>
static void registerClass()
{
constructors().insert( T::staticMetaObject.className(), &constructorHelper<T> );
} static QObject* createObject( const QByteArray& className, QObject* parent = NULL )
{
Constructor constructor = constructors().value( className );
if ( constructor == NULL )
return NULL;
return (*constructor)( parent );
} private:
typedef QObject* (*Constructor)( QObject* parent ); template<typename T>
static QObject* constructorHelper( QObject* parent )
{
return new T( parent );
} static QHash<QByteArray, Constructor>& constructors()
{
static QHash<QByteArray, Constructor> instance;
return instance;
}
}; #endif // OBJECTFACTORY_H

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

//使用方法
ObjectFactory fac;
fac.registerClass<TestObject>();
qDebug()<<"begin-------------------------------"<<endl;
TestObject* object = qobject_cast<TestObject*>(fac.createObject( "TestObject" , this));
object->setText("template factory");
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. nbu虚拟机恢复样例(之后补图)

    9.2.1进入Backup,Archive,and Restore管理器 9.2.2选择客户端和策略类型 9.2.3选择恢复的虚拟机 9.2.4恢复虚拟机到不同目录 9.2.5更改虚拟机名称和存储 因 ...

  2. 小样本学习(few-shot learning)在文本分类中的应用

    1,概述 目前有效的文本分类方法都是建立在具有大量的标签数据下的有监督学习,例如常见的textcnn,textrnn等,但是在很多场景下的文本分类是无法提供这么多训练数据的,比如对话场景下的意图识别, ...

  3. uboot向kernel的传参机制——bootm与tags

    http://blog.csdn.net/skyflying2012/article/details/35787971 最近阅读代码学习了uboot boot kernel的过程以及uboot如何传参 ...

  4. 201871010102-常龙龙《面向对象程序设计(java)》第四周学习总结

    博文正文开头: 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu ...

  5. Logstash 学习资料

    学习资料 网址 Logstash Reference(官方) https://www.elastic.co/guide/en/logstash/current/introduction.html

  6. NOIP 2008 立体图

    洛谷 P1058 立体图 洛谷传送门 JDOJ 1541: [NOIP2008]立体图 T4 JDOJ传送门 题目描述 小渊是个聪明的孩子,他经常会给周围的小朋友们将写自己认为有趣的内容.最近,他准备 ...

  7. 2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017)

    2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017) 全靠 wxh的博客 补完这套.wx ...

  8. (HK1-2)海康相机直接连接电脑不经过路由器设置

    解决电脑无法通过网线直连海康摄像机的问题 https://blog.csdn.net/u014552102/article/details/86708371 一.现象:    通过博主的另外一篇博客h ...

  9. Docker入门之安装Docker

    目录 目录 1 1. 前言 1 2. 创建网桥 2 3. 安装Docker 2 3.1. 二进制安装 3 3.1.1. 下载安装 3 3.1.2. 配置服务 3 3.1.3. 启动服务 4 3.2. ...

  10. 【CF10D】 LCIS

    题目链接 最长公共上升子序列 \(f[i][j]\)表示\(A\)的前\(i\)个数,匹配\(B\)的第\(j\)个数,且\(B[j]\)必选时的最长公共上升子序列长度 转移: if(A[i]==B[ ...