Qt中的反射机制之Q_PROPERTY
Hello大家好,本篇文章继续为大家介绍Qt的核心内容。
学习过Java的朋友肯定都听说过“反射”一词,所谓反射,就是对于任意一个类,在运行状态下都能够知道这个类的所有属性和方法,并可以对这些方法动态调用的一种机制。
反射可以用于编写服务框架程序时,通过配置的手段,动态的加载不同方法;也可用于网络传输中传输对象等。
但是,很遗憾,我们所学习的C++本身并没有支持反射这一机制,但是通过Qt中的元对象系统,有了对反射的很好支持。
在讲述反射编程之前,需要先掌握QMetaObject,QMetaProperty,QVariant,和Q_PROPERTY。
本篇文章,就先为大家介绍Q_PROPERTY(…)宏的用法。
Qt之所以能支持反射,是因为在编译C++代码之前,使用了moc元对象编译器。moc读取一个C++头文件,如果它发现一个或多个包含Q_OBJECT宏的类声明,它将生成一个包含这些类的元对象代码的C++源文件。而用以支持元对象系统或是反射机制的代码也包含其中。
所以Qt中使用Q_PROPERTY宏来告诉moc用以支持类的哪些属性。
Q_PROPERTY宏的声明如下:
其中,属性名称、属性类型和获取属性的READ函数是必须提供的参数。其他项是可选的,但WRITE函数最好也要有。(这里只对属性名称,READ,WRITE参数作介绍,其它参数等用到了再作详细介绍)
下面,请看一个例子:
新建一个空的控制台工程,取名为MetaProperty
mystudent.h
#ifndef MYSTUDENT_H
#define MYSTUDENT_H
#include <QObject>
/*
* 学生类
* 该类继承QObject,并且Q_OBJECT宏被包含在私有段中,以便moc生成可支持属性系统的C++代码
*/
class MyStudent : public QObject
{
Q_OBJECT
//id代表属性m_id的名称,类型为QString()
//推荐属性使用“m_属性名称”的形式
//READ函数使用“get属性名称”的形式
//WRITE函数使用“set属性名称”的形式
Q_PROPERTY(QString id READ getId WRITE setId)
Q_PROPERTY(QString name READ getName WRITE setName)
Q_PROPERTY(Sex sex READ getSex WRITE setSex)
//用来生成字符串到枚举值的转换函数
Q_ENUMS(Sex)
public:
enum Sex//性别
{
Man, //男
Woman//女
};
explicit MyStudent(QObject *parent = 0);
QString getId() const;
void setId(const QString &id);
QString getName() const;
void setName(const QString &name);
Sex getSex() const;
QString getSexString() const;
void setSex(const Sex &sex);
void setSex(const QString& sex);
private:
QString m_id; //学生id
QString m_name; //学生姓名
Sex m_sex; //学生性别
};
#endif // MYSTUDENT_H
mystudent.cpp
#include <QMetaProperty>
#include <QVariant>
#include "mystudent.h"
MyStudent::MyStudent(QObject *parent) : QObject(parent)
{
}
QString MyStudent::getId() const
{
return m_id;
}
void MyStudent::setId(const QString &id)
{
m_id = id;
}
QString MyStudent::getName() const
{
return m_name;
}
void MyStudent::setName(const QString &name)
{
m_name = name;
}
MyStudent::Sex MyStudent::getSex() const
{
return m_sex;
}
QString MyStudent::getSexString() const
{
return property("Sex").toString();
}
void MyStudent::setSex(const Sex &sex)
{
m_sex = sex;
}
void MyStudent::setSex(const QString &sex)
{
//首先获取元对象指针
static const QMetaObject* meta = metaObject();
//根据属性名称Sex,查找m_sex属性对象QMetaProperty
static int propindex = meta->indexOfProperty("sex");
static const QMetaProperty mp = meta->property(propindex);
//QMetaProperty中的方法enumerator可以将字符串转化成枚举值
//如果给定的字符串不与任何枚举值匹配,则返回-1
QMetaEnum menum = mp.enumerator();
const char* ntyp = sex.toStdString().c_str();
m_sex = static_cast<Sex>(menum.keyToValue(ntyp));
}
main.cpp
#include <QVariant>
#include "mystudent.h"
int main()
{
MyStudent student;
student.setId("1");
student.setName("Tom");
student.setSex(MyStudent::Man);
Q_ASSERT(student.getSex()==MyStudent::Man);
//通过属性名称获取属性值
QVariant v = student.property("id");
QString str = v.toString();
Q_ASSERT("1"==str);
student.setProperty("id", QVariant("2"));
Q_ASSERT("2"==student.getId());
student.setSex("Woman");
Q_ASSERT(student.getSex()==MyStudent::Woman);
}
使用setProperty()和property()可以设置和获取由Q_PROPERTY宏包含的属性。
关于Q_PROPERTY宏的介绍就先到这里了。
欢迎关注微信公众号"小豆君Qt分享",最新文章都会在公众号第一时间发布,或者你有不懂的问题,关注公众号后,可加好友或进Qt群获得答案。