反射

-在计算机科学中,反射是指计算机程序在运行时(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. MySQL单表数据不要超过500万行:是经验数值,还是黄金铁律?

    本文阅读时间大约3分钟. 梁桂钊 | 作者 今天,探讨一个有趣的话题:MySQL 单表数据达到多少时才需要考虑分库分表?有人说 2000 万行,也有人说 500 万行.那么,你觉得这个数值多少才合适呢 ...

  2. 线上IIS应用程序池自动关闭

    事情的经过是这样的: 下午下班的铃声已经敲响,我已经整装待发.突然同事说某水司的微信公众号不能正常访问了.点击营业厅,直接提示Service Unavailable. 立马远程服务器查看,IIS微信公 ...

  3. linux环境安装配置nginx

    安装依赖 yum install gcc yum install pcre-devel yum install zlib zlib-devel yum install openssl openssl- ...

  4. 【IOS】libimobiledevice常用命令

    libimobiledevice 是一个跨平台的软件库,支持 iPhone®, iPod Touch®, iPad® and Apple TV® 等设备的通讯协议.   安装 命令: brew ins ...

  5. 201871010131-张兴盼《面向对象程序设计(java)》第二周学习总结

    项目 内容 <面向对象程序设计(java)> https://home.cnblogs.com/u/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.c ...

  6. java JSONObject

    JSONObject.has("key")方法首先判断是否含有该key字段,如果不存在该字段,返回false;如果存在此字段,还判断了该字段的value值是否为null,如果val ...

  7. 201800624模拟赛T2——回家路上

    题目描述 很多学生都抱怨浪费在回家路上的时间太长.这天dongdong刚走出学校大门,就听说某段路在施工(但不知道是哪条路),有可能导致他回家的时间会变长. Dongdong给出了一张地图,图中标号为 ...

  8. 修改JDK安装路径的作用

    JDK的默认安装路径是Program Files文件夹,而Program Files的两个英文单词间有空格, 而当JDK的安装路径里包含空格时,在设置CLASSPATH时,可能会引发莫名奇妙的错误, ...

  9. 11-散列2 Hashing (25 分)

    The task of this problem is simple: insert a sequence of distinct positive integers into a hash tabl ...

  10. AQS源码的简单理解

    概念 AQS全称 AbstractQueuedSynchronizer. AQS是一个并发包的基础组件,用来实现各种锁,各种同步组件的.它包含了state变量.加锁线程.等待队列等并发中的核心组件. ...