目录
[Qt开发探幽(二)]浅谈关于元对象,宏和Q_ENUM
前言
最近在开发的时候,我自己写了一套虚函数。这也是我第一次写这么大一个框架,遇到了一些有点莫名其妙的问题(也不能算莫名奇妙,只能说有点玩不明白),详情可以见
前两天我写了一些demo验证了一些我的想法,算是在元对象编程里简单的游了一游。
一、元对象
Qt的元对象是一个让人又爱又恨的东西。让人爱是因为它确实功能强大,可以允许我们从类、枚举类型、获得一些我们在正常C++开发中可能无法正常获取到的东西。比如最简单的:在正常C++开发中,枚举类型的类型名称对于C++而言只是一个有一个的十六进制码,而不是字符串的形式,也不可能获得字符串,那么可能就有如下的奇技淫巧:
没错,以上就是通过 Qt的元对象类型将一个枚举类型的成员转换成字符串,或者将字符串转回枚举类型的值
更变态的是什么?
更变态的是,通过元对象类型我们可以实现一个更夸张的功能:让一个类和一个Json字符串之间做转换:
当然了,做转换的前提是使用Q_PROPERTY宏包裹着属性,这样这个属性就被注册进了这个类的元对象系统内,然后就可以通过一些奇技淫巧,来实现类成员变量和字符串之间的转换了,以下是一个例子:
#pragma region Lev_Json
/// <summary>
/// name:Lev_Json
/// 说明:此类用作辅助参数类与json字符串之间的转换,使用此类请使用Q_PROPERTY声明所有的类成员变量
/// </summary>
class Lev_Json : QObject {
public:
template<class T1>
static bool ValidateJsonKeys(const QString& jsonString, const T1* T_Class) {
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8());
if (!jsonDoc.isObject()) {
return false;
}
QJsonObject jsonObject = jsonDoc.object();
const QMetaObject* metaObject = T_Class->metaObject();
for (int i = 0; i < metaObject->propertyCount(); ++i) {
QMetaProperty property = metaObject->property(i);
QString propName = property.name();
if (propName.contains("objectName"))
continue;
if (!jsonObject.contains(propName)) {
return false;
}
}
return true;
}
/// <summary>
/// 判断这个Json字符串对于这个Object而言是否合法
/// </summary>
/// <typeparam name="T1"></typeparam>
/// <param name="jsonString"></param>
/// <returns></returns>
template<class T1>
static bool ValidateJsonKeys(const QString& jsonString, QSharedPointer<T1> T_Class_1) {
QObject* T_Class = dynamic_cast<QObject*>(T_Class_1.data());
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8());
if (!jsonDoc.isObject()) {
return false; // Return false if JSON is not an object
}
QJsonObject jsonObject = jsonDoc.object();
const QMetaObject* metaObject = T_Class->metaObject();
for (int i = 0; i < metaObject->propertyCount(); ++i) {
QMetaProperty property = metaObject->property(i);
QString propName = property.name();
if (!jsonObject.contains(propName)) {
return false;
}
}
return true;
}
/// <summary>
/// 推荐,序列化Qt对象,请用Q_PROPERTY包裹成员变量,使用内存安全的QSharedPointer
/// </summary>
/// <typeparam name="T1">模板对象,可以不声明,会自动识别</typeparam>
/// <param name="T_Class_1">输入的对象</param>
/// <returns></returns>
template<class T1>
static QString JsonSerialization(QSharedPointer<T1> T_Class_1) {
QJsonObject ret;
QObject* T_Class = dynamic_cast<QObject*>(T_Class_1.data());
const QMetaObject* metaObject = T_Class->metaObject();
for (int i = 0; i < metaObject->propertyCount(); ++i) {
QMetaProperty property_ = metaObject->property(i);
QVariant propValue = property_.read(T_Class);