将数据存储为一个Private结构体类型的成员变量d:

<qvariant.cpp>

1 QVariant::QVariant(Type type)
2 { create(type, 0); }
1 void QVariant::create(int type, const void *copy)
2 {
3 d.type = type;
4 handler->construct(&d, copy);
5 }
static void construct(QVariant::Private *x, const void *copy)
{
x->is_shared = false; switch (x->type) {
case QVariant::String:
v_construct<QString>(x, copy);
break;
......
default:
void *ptr = QMetaType::construct(x->type, copy);
if (!ptr) {
x->type = QVariant::Invalid;
} else {
x->is_shared = true;
x->data.shared = new QVariant::PrivateShared(ptr);
}
break;
}
x->is_null = !copy;
}
1 QVariant::QVariant(int val)
2 { d.is_null = false; d.type = Int; d.data.i = val; }

<qvariant.h>

class Q_CORE_EXPORT QVariant
{
......
struct Private
{
inline Private(): type(Invalid), is_shared(false), is_null(true) { data.ptr = 0; }
inline Private(const Private &other)
: data(other.data), type(other.type),
is_shared(other.is_shared), is_null(other.is_null)
{}
union Data
{
char c;
int i;
uint u;
bool b;
double d;
float f;
qreal real;
qlonglong ll;
qulonglong ull;
QObject *o;
void *ptr;
PrivateShared *shared;
} data;
uint type : 30;
uint is_shared : 1;
uint is_null : 1;
};
......
Private d;
......
}

QVariant支持的数据类型:

 1 enum Type {
2 Invalid = 0,
3
4 Bool = 1,
5 Int = 2,
6 UInt = 3,
7 LongLong = 4,
8 ULongLong = 5,
9 Double = 6,
10 Char = 7,
11 Map = 8,
12 List = 9,
13 String = 10,
14 StringList = 11,
15 ByteArray = 12,
16 BitArray = 13,
17 Date = 14,
18 Time = 15,
19 DateTime = 16,
20 Url = 17,
21 Locale = 18,
22 Rect = 19,
23 RectF = 20,
24 Size = 21,
25 SizeF = 22,
26 Line = 23,
27 LineF = 24,
28 Point = 25,
29 PointF = 26,
30 RegExp = 27,
31 Hash = 28,
32 EasingCurve = 29,
33 LastCoreType = EasingCurve,
34
35 // value 62 is internally reserved
36 #ifdef QT3_SUPPORT
37 ColorGroup = 63,
38 #endif
39 Font = 64,
40 Pixmap = 65,
41 Brush = 66,
42 Color = 67,
43 Palette = 68,
44 Icon = 69,
45 Image = 70,
46 Polygon = 71,
47 Region = 72,
48 Bitmap = 73,
49 Cursor = 74,
50 SizePolicy = 75,
51 KeySequence = 76,
52 Pen = 77,
53 TextLength = 78,
54 TextFormat = 79,
55 Matrix = 80,
56 Transform = 81,
57 Matrix4x4 = 82,
58 Vector2D = 83,
59 Vector3D = 84,
60 Vector4D = 85,
61 Quaternion = 86,
62 LastGuiType = Quaternion,
63
64 UserType = 127,
65 #ifdef QT3_SUPPORT
66 IconSet = Icon,
67 CString = ByteArray,
68 PointArray = Polygon,
69 #endif
70 LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type
71 };

数据类型转换:

以下数据类型可以自动转换

可通过成员函数bool QVariant::canConvert ( Type t ) const确定是否可执行指定数据类型的转换

自定义QVariant可存储的数据类型:

class Q_CORE_EXPORT QVariant
{
......
template<typename T>
bool canConvert() const
{ return canConvert(Type(qMetaTypeId<T>())); }
......
}
 
1 static inline QVariant fromValue(const T &value)
2 { return qVariantFromValue(value); }
template <typename T>
inline QVariant qVariantFromValue(const T &t)
{
return QVariant(qMetaTypeId<T>(reinterpret_cast<T *>(0)), &t, QTypeInfo<T>::isPointer);
}

从类的声明中可以看出,要成为QVariant可存储的数据类型,必须将该自定义数据类型通过宏Q_DECLARE_METATYPE (Type)注册到MetaType系统中

<qmetatype.h>

 1 #define Q_DECLARE_METATYPE(TYPE)                                        \
2 QT_BEGIN_NAMESPACE \
3 template <> \
4 struct QMetaTypeId< TYPE > \
5 { \
6 enum { Defined = 1 }; \
7 static int qt_metatype_id() \
8 { \
9 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
10 if (!metatype_id) \
11 metatype_id = qRegisterMetaType< TYPE >(#TYPE, \
12 reinterpret_cast< TYPE *>(quintptr(-1))); \
13 return metatype_id; \
14 } \
15 }; \
16 QT_END_NAMESPACE

示例:

namespace MyNamespace
{
struct MyStruct
{
int i;
...
};
} Q_DECLARE_METATYPE(MyNamespace::MyStruct)
 1 MyStruct s;
2 QVariant var;
3 var.setValue(s);
4
5 ......
6
7 QVariant var2 = QVariant::fromValue(s);
8 if (var2.canConvert<MyStruct>())
9 {
10 MyStruct s2 = var2.value<MyStruct>();
11 }

http://www.cnblogs.com/paullam/p/3706371.html

QVariant相当于一个包含大多数Qt数据类型的联合体(源码解读)的更多相关文章

  1. 如何判断一个Http Message的结束——python源码解读

    HTTP/1.1 默认的连接方式是长连接,不能通过简单的TCP连接关闭判断HttpMessage的结束. 以下是几种判断HttpMessage结束的方式: 1.      HTTP协议约定status ...

  2. Qt update刷新之源码分析(一)

    在做GUI开发时,要让控件刷新,会调用update函数:那么在调用了update函数后,Qt究竟基于什么原理.执行了什么代码使得屏幕上有变化?本文就带大家来探究探究其内部源码. Qt手册中关于QWid ...

  3. 分享一个与ABP配套使用的代码生成器源码

    点这里进入ABP系列文章总目录 分享一个与ABP配套使用的代码生成器源码 真对不起关注我博客的朋友, 因最近工作很忙, 很久没有更新博客了.以前答应把自用的代码生成器源码共享出来, 也一直没有时间整理 ...

  4. 整合了一个功能强大完善的OA系统源码,php全开源 界面漂亮美观

    整合了一个功能强大完善的OA系统源码,php全开源界面漂亮美观.需要的同学联系Q:930948049

  5. IM即时通讯设计 高并发聊天服务:服务器 + qt客户端(附源码)

    来源:微信公众号「编程学习基地」 目录 IM即时通信程序设计 IM即时通讯 设计一款高并发聊天服务需要注意什么 如何设计可靠的消息处理服务 什么是粘包 什么是半包 解决粘包和半包 IM通信协议 应用层 ...

  6. Qt事件分发机制源码分析之QApplication对象构建过程

    我们在新建一个Qt GUI项目时,main函数里会生成类似下面的代码: int main(int argc, char *argv[]) { QApplication application(argc ...

  7. koa2源码解读及实现一个简单的koa2框架

    阅读目录 一:封装node http server. 创建koa类构造函数. 二:构造request.response.及 context 对象. 三:中间件机制的实现. 四:错误捕获和错误处理. k ...

  8. 分享一个基于web的满意度调查问卷源码系统

    问卷调查系统应用于各行各业,对于企业的数据回收统计分析战略决策起到至关作用.而现有的问卷调查系统大都是在线使用并将数据保存在第三方服务器上.这种模式每年都要缴纳费用并且数据安全性得不到保证.所以说每个 ...

  9. Android Studio 一个完整的APP实例(附源码和数据库)

    前言: 这是我独立做的第一个APP,是一个记账本APP. This is the first APP, I've ever done on my own. It's a accountbook APP ...

随机推荐

  1. 05-session-会话跟踪技术

    1.session简介 Django中默认支持Session,其内部提供了5种类型的Session供开发者使用: 数据库(默认) 缓存 文件 缓存+数据库 加密cookie Session是服务器端技 ...

  2. ssm 配置事务回滚

    参考:https://blog.csdn.net/Mint6/article/details/78363761 在 applicationContext.xml 中配置好了事务和数据源等必须要用到的配 ...

  3. 关于 Git SSH 使用的项目实践

    Git 是分布式的代码管理工具,远程的代码管理是基于 SSH 的,所以要使用远程的 git 则需要SSH的配置. 一.简述 访问 Git 仓库可以使用 SSH Key 的方式,首先需要生成 Key. ...

  4. yolo算法框架使用二

    6,voc数据集训练模型 1)下载数据集 官网提供一些voc数据,是基于2007年到2012年的,你可以通过以下地址下载到: wget https://pjreddie.com/media/files ...

  5. Mybatis批量更新报错com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException

    批量更新数据,非常简单的一段代码,硬是报错,插入的数据也能显示出来 List<User> userlist = new ArrayList<User>(); userlist. ...

  6. python魔法方法大全

    1.python魔法方法详解: python魔法方法是可以修改重载的,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而 ...

  7. 我的第一个bootstrap实例

    先上代码: <!doctype html><html lang="en"><head> <meta charset="UTF-8 ...

  8. centos7 --ngnix 常用命令:

    配置命令 随服务器启动 # systemctl enable nginx.service 重启 nginx 服务 # systemctl restart nginx.service 停止 nginx ...

  9. Hyperledger Fabric 1.2 --- Chaincode Operator 解读和测试(二)

    本文接上一节是测试部分 搭建一个模拟测试环境 作者将fabric release1.2工程中的 example-e2e进行了改造来进行本次实验: (1)首先我们将examples/e2e_cli/sc ...

  10. Mac下基于testrpc和truffle的以太坊智能合约开发环境搭建

    原文地址:石匠的blog truffle是一个基于Javascript开发的一套智能合约开发框架,使用Solidity语言编写合约.truffle有一套自动的项目构建机制,集成了开发,测试和部署的各个 ...