软件特攻队|Qt中的反射机制之Q_PROPERTY

接触过Java的同学肯定知道“反射”这一神器,而所谓的反射,指的是对于任意的一个类,即使在运行状态下,都能知道这个类的所有方法和属性,并可以动态调用这些方法的一种机制。

但是非常遗憾的是,C++本身并不支持反射。不过现如今我们可以通过Qt中的元对象系统,享受反射带来的好处。

要想掌握反射编程的精髓,首先需要掌握QMetaObject,QMetaProperty,QVariant,和Q_PROPERTY。

而这里就先为大家介绍Q_PROPERTY(…)宏的用法。

我们了解到Qt之所以具有反射机制,是由于在编译C++代码之前,先行使用了moc元对象编译器。moc读取了一个C++头文件后,如果发现它具有一个或多个包含Q_OBJECT宏的类声明,它将生成一个包含这些类的元对象代码的C++源文件。而能够支持元对象系统或是反射机制的代码也包含其中。

我们看一个例子:

mystudent.h

#ifndef MYSTUDENT_H

#define MYSTUDENT_H

#include<QObject>

/*

* 学生类

* 该类继承QObject,并且Q_OBJECT宏被包含在私有段中,以便moc生成可支持属性系统的C++代码

*/

classMyStudent: publicQObject

{

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:

enumSex//性别

{

Man, //男

Woman//女

};

explicitMyStudent(QObject*parent = 0);

QString getId() const;

void setId(constQString&id);

QString getName() const;

void setName(constQString&name);

Sex getSex() const;

QString getSexString() const;

void setSex(constSex&sex);

void setSex(constQString& 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)

{

}

QStringMyStudent::getId() const

{

return m_id;

}

voidMyStudent::setId(constQString&id)

{

m_id = id;

}

QStringMyStudent::getName() const

{

return m_name;

}

voidMyStudent::setName(constQString&name)

{

m_name = name;

}

MyStudent::SexMyStudent::getSex() const

{

return m_sex;

}

QStringMyStudent::getSexString() const

{

returnproperty(“Sex”).toString();

}

voidMyStudent::setSex(constSex&sex)

{

m_sex = sex;

}

voidMyStudent::setSex(constQString&sex)

{

//首先获取元对象指针

staticconstQMetaObject* meta = metaObject();

//根据属性名称Sex,查找m_sex属性对象QMetaProperty

staticint propindex = meta->indexOfProperty(“sex”);

staticconstQMetaProperty mp = meta->property(propindex);

//QMetaProperty中的方法enumerator可以将字符串转化成枚举值

//如果给定的字符串不与任何枚举值匹配,则返回-1

QMetaEnum menum = mp.enumerator();

constchar* 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()可以设置和获取由QPROPERTY宏包含的属性。

最后就运行一下程序,体会下Q_PROPERTY的用法吧。

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2020年3月3日
下一篇 2020年3月3日

相关推荐