经典的QVariant设计之道

简介: 经典的QVariant设计之道

今天,分享下QVariant的用法

Variant中文翻译为“变体,转化”,那么我们该如何理解这个类呢,如下。

1 Qt为什么会提供QVariant类

当我们要理解一个新的事物时,用生活中常见的事物作类比,会帮助我们加深对这个新事物的理解程度和准确度。

在世界上还没有发明集装箱之前,所有的货物都是直接通过卡车运送至港口,再由港口的装卸工搬运至货船,由于所有的货物大小形状规格不同,导致装至船上的货物远远小于一艘船的实际承载量。而一次远航,就需要花费很长的周期和高昂的开销。对于海运的货物就变得非常昂贵。

而在出现集装箱之后,工厂生产的产品可以直接装在标准的集装箱中,所有的集装箱可以平整的放在运输船上,一艘船便可以运送大量的货物,从而产品价格低廉,增加了各个国家的经济来往,这也改变了世界的经济格局。

那么,你有没有想到,为什么这么简单的设计就改变了世界呢。这源自于集装箱屏蔽了每种产品的大小形状上的差异性,对外提供了一致的形状,那么所有的周边产品,例如港口的起重机,货船的设计都可以依据集装箱的标准而进行有效的设计。

好了,现在我们回到QVariant类(类比集装箱的特点),它正是屏蔽了不同类型的数据结构之间的差异性,从而可以让数据以一种标准的形式在类之间,函数之间,对象之间进行传递,就像集装箱让产品在不同国家之间进行传递一样,那么我们就可以依据QVariant提供的标准型,在其之上建立起足够通用便捷的代码。

例如,当一个函数使用QVariant作为参数时,这恰好就提供了这样的便捷性。就拿我们上篇文章的例子setProperty,因为第二个参数value要为所有的类型提供通用转换方法,那么使用QVariant作为这些类型的存储变量,那是再合适不过了。

QObject::setProperty(const char *name, const QVariant &value)

当我们想要再获取该变量时,就使用property接口,用QVariant提供的toT方法进行转换,从而得到我们想要的值。这是一个多么便捷的做法啊,我还真惊叹于实现者的思维方式。从某种意义上讲,这也可能是多态的另一种表现方式。

2 QVariant

QVariant支持多种数据类型的转换,包括C++的所有基本类型,Qt提供的基本类型,甚至还可以支持自定义类型的转换

下图是其支持的类型(仅列出了一部分,详细类型可以查看帮助文档或头文件声明)

微信图片_20230103150242.jpg

常用函数:

QVariant::canConvert(int targetTypeId) const

如果变量的类型可以转换为请求的类型targetTypeId,则返回true。


bool QVariant::convert(int targetTypeId)

将变量转换为请求的类型targetTypeId。如果转换不能完成,则清除变量。如果成功转换了变量的当前类型,则返回true;否则返回false。


T QVariant::value() const

返回转换为模板类型T的存储值。如果不能转换该值,将返回一个默认构造的值。


static QVariant QVariant::fromValue(const T &value)

返回一个包含值副本的QVariant。否则,其行为与setValue()完全相同。


下面是一个例子:

#include <QVariant>
#include <QPoint>
#include <QDebug>
class MyClass
{
public:
    MyClass():i(0){}
    friend QDebug operator<<(QDebug d, const MyClass &c);
private:
    int i;
};
//注意,如果想要自定义的MyStruct也支持QVariant,那么需要Q_DECLARE_METATYPE向Qt元对象系统进行注册
Q_DECLARE_METATYPE(MyClass)
QDebug operator<<(QDebug d, const MyClass &c)
{
    d << "MyStruct(" << c.i << ")";
}
int main(int argc, char *argv[])
{
    QVariant v = 42;
    qDebug() << "v.canConvert<int>(): " << v.canConvert<int>() << v.toInt();
    qDebug() << "v.canConvert<QString>()" << v.canConvert<QString>() << v.toString();
    qDebug() << "v.canConvert<QPoint>()" << v.canConvert<QPoint>() << v.toPoint();
    qDebug() << "v covert to QString before:" << v;
    v.convert(QVariant::String);
    qDebug() << "v covert to QString after:" << v;
    v.convert(QVariant::Point);//如果无法转换,则QVariant本身会被清空
    qDebug() << "v covert to QPoint after:" << v;
    //支持自定义类型
    MyClass c;
    v.setValue(c);
    //...
    MyClass c2 = v.value<MyClass>();
    qDebug() << c2;
}


综上,QVariant可以在函数之间进行传递,同样的,我们也可以在类之间,甚至网络之间进行传递,而对象序列化也是需要QVariant这样的特性。

在今后的设计中,即使我们不使用QVariant,但是这样的思维模式是需要我们来学习的,屏蔽不同物体之间的差异,提供标准化的接口,然后依据该标准建造自己的框架体系。


好了,这次的分享就到这里,我们下次再见,最后不要忘记点赞和分享哦,您的支持就是对原创,分享的最大鼓励。


欢迎关注微信公众号-小豆君Qt分享

相关文章
|
Android开发
Android Studio解决导入别人源码报红问题
当我们下载别人的源码导入到自己的Android Studio中时可能出现各种红色警告,不管是Clean Project还是Rebuild Project都不管用,但是尴尬的是源码还能正常运行,那我们该如何解决呢? 解决方法 :点击左上角File——>Invalidate Caches/Restarts.
2311 0
|
5月前
|
安全 数据管理 测试技术
告别蛮力:让测试数据生成变得智能而高效
告别蛮力:让测试数据生成变得智能而高效
554 120
|
机器学习/深度学习 运维 监控
万亿参数模型训练神器:Kubeflow 2025量子加速版下载与TPU集群配置详解
Kubeflow 2025 是一个云原生机器学习操作系统,实现了四大突破性创新:量子混合训练(支持经典-量子混合神经网络协同计算)、神经符号系统集成(融合深度学习与逻辑推理引擎)、边缘智能联邦(5G MEC节点自动弹性扩缩容)和因果可解释性框架(集成Pearl、DoWhy等工具链)。该平台通过混合计算架构、先进的硬件配置矩阵和量子增强型安装流程,提供了从基础设施预配置到核心组件安装和安全加固的完整部署方案。此外,Kubeflow 2025 还涵盖全生命周期开发实战案例、智能运维监控体系、安全与合规框架以及高阶调试技巧,帮助用户高效构建和管理复杂的机器学习项目。
|
算法 安全 网络安全
数据结构之网络攻击路径(深度优先搜索)
本文介绍了如何使用深度优先搜索(DFS)算法分析网络攻击路径。在网络安全领域,DFS用于检测网络中潜在的攻击路径,帮助安全人员及时发现并阻止威胁。文中详细描述了网络图的构建、节点间的连接关系以及DFS的实现过程。通过一个具体的例子,展示了如何检测从一个普通节点到关键节点的攻击路径,并讨论了DFS算法的优缺点。提供的C++代码实现了网络图的构建和攻击路径的检测功能。
346 24
|
数据采集 存储 JSON
【专栏】网络爬虫与数据抓取的基础知识,包括爬虫的工作原理、关键技术和不同类型
【4月更文挑战第27天】本文介绍了网络爬虫与数据抓取的基础知识,包括爬虫的工作原理、关键技术和不同类型。通过实例展示了如何构建简单爬虫,强调实战中的环境搭建、目标分析及异常处理。同时,文章探讨了法律、伦理考量,如尊重版权、隐私保护和合法用途,并分享了应对反爬策略。最后,倡导遵守数据抓取道德规范,以负责任的态度使用这项技术,促进数据科学的健康发展。
1693 2
|
存储 监控 关系型数据库
MySQL造数据占用临时表空间
MySQL造数据占用临时表空间
296 0
|
SQL BI 网络安全
SQL Server2014的安装与配置
SQL Server2014的安装与配置
1198 0
|
弹性计算 数据库连接 Nacos
阿里云ECS服务器在docker中部署nacos
docker pull nacos 失败,docker部署nacos遇到的问题,nacos数据库连接,nacos端口映射
899 1
|
缓存 Java 数据库
kswapd0 进程CPU占用过高
kswapd0 进程CPU占用过高
1360 2
kswapd0 进程CPU占用过高
|
JSON Prometheus Cloud Native
AlertManager实现webhook告警(使用Postman测试)
🍅程序员小王的博客:程序员小王的博客 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 如有编辑错误联系作者,如果有比较好的文章欢迎分享给我,我会取其精华去其糟粕 🍅java自学的学习路线:java自学的学习路线 🍋相关学习资料及其参考文章:prometheus手册,邮件和微信告警,Alertmanager篇 🍊 可以去个人博客网站查看本博客排版更清晰:AlertManager ———————————————— 版权声明:本文为CSDN博主「程序员小王java」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn
2195 0
AlertManager实现webhook告警(使用Postman测试)

热门文章

最新文章