浅析Qt中的反射编程

浅析Qt中的反射编程

一、反射的基本思想

可能你听过Java中的反射概念,但是C++中却没有,不过Qt中支持反射的基本思想。

所谓反射,就是指对象成员之间的自我检查。

使用反射编程就可以编写出通用的操作,就能对具有各种不同结构的类进行操作

二、元对象模式

我们知道要想实现Qt的信号和槽功能,我们就必须有Qt的元对象系统,因为这个元对象系统提供了对象之间通信的信号与槽机制、运行时类型信息和动态属性系统等。

但是,元对象是基于三个条件的:

 1、该类必须继承自Qobject类

 2、必须在类的私有声明区声明Q_OBJECT宏(在类定义的时候,如果没有指定public,
则默认为private,用来启用元对象功能,比如动态属性、信号和槽)。 

 3、 元对象编译器Meta-Object Compiler(moc)为 QObject的子类实现元对象 
特性提供必要的代码。

对于上述第三个条件,涉及到元对象的概念。

元对象:就是描述另一个对象结构的对象。

QMeteObject是元对象模式的一个Qt实现,它提供了一个QObject对象所拥有的属性和方法的信息。元对象模式有时也称为反射模式。

一个拥有元对象的类就可以支持反射,这是一个面向对象语言都具有的性质。虽然C++中不支持反射,但是Qt的元对象编译器(MetaObject compiler,moc)可以为QObject生成支持这种机制的代码。

当我们创建一个继承自QObject的类时,都会拥有由moc生成QMetaObject。QObject拥有一个成员函数,它能够返回指向对象的QMetaObject的指针。

这个函数的原型是:

QMetaObject* QObject::metaObject() const [virtual]

可以使用QMetaObject的一些方法来获取一个QObject的信息。

className() 将类名以const char *的格式返回
superClass() 如果存在基类的QMetaObject,则返回其指针,如果不存在,返回0。
methodCount() 返回类的成员函数个数。
inherits() 判断类的继承关系。
tr()、trUtf8() 国际化使用。
setProperty()、property() 通过名称来动态设置和获取属性。
newInstance() 创建实例。

三、实例

通过继承QObject类,创建一个类。

class MyCustomer : public QObject
{

    Q_OBJECT

    Q_PROPERTY( QString id READ getId WRITE setId );
    Q_PROPERTY( QString name READ getName WRITE setName );

public:
    enum CustType{One, Two, Three};

    Q_ENUMS( CustType );

    explicit MyCustomer(const QString name = QString(), QObject* parent = 0);
    Q_INVOKABLE QString getId() const{ return m_id;}
    Q_INVOKABLE void setId(const QString &id){ m_id = id;}
    Q_INVOKABLE QString getName() const{ return m_name;}
    Q_INVOKABLE void setName(const QString &name){ m_name = name;}

private:
    QString m_id;
    QString m_name;
    CustType m_type;
};

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

同时在运行时也可以做一些遍历该类成员的操作。

通过对这个类中的属性和方法,就完成了自身的检查,即反射。

四、具体应用

在使用Qt Designer工具时,对于其中的控件,Qt Designer不知道放入插件的类型、方法和属性。将插件导入的时候可以检测该空间的类型、方法和属性,将这些属性显示在窗口中。

本文原创作者:冯一川([email protected]),未经作者授权同意,请勿转载。

你可能感兴趣的:(Qt学习之路,qt,开发语言)