将数据存储为一个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. burpsuite 抓取https 证书问题

    一定要按照步骤来,先导入burp初始证书到服务器,这时候初始证书是未验证的,然后导出为crt/cer文件(可能拼写错误,总之是正规证书后缀),再导入到机构. 要代理所有类型包括ssl的才能正常导入机构 ...

  2. 有关onpropertychange事件

    <div style="border:1px solid #fc0;height:24px;width:300px;" id="target">&l ...

  3. 利用VBS脚本实现Telnet自动连接

    把以下代码保存为*.vbs文件,替换IP.用户名.密码. Dim objShell Set objShell = CreateObject("Wscript.Shell") obj ...

  4. eclipse生成ant build.xml打war包

      背景: 最近想实现jenkins+ant命令一键打war包,部署到测试环境,然后自动化接口测试,结果发现用eclipse本身导出的ant buildfiles文件,打包出来都是空文件.很多代码都没 ...

  5. [Unity] unity5.3 assetbundle打包及加载

    Unity5.3更新了assetbundle的打包和加载api,下面简单介绍使用方法及示例代码. 在Unity中选中一个prefab查看Inspector窗口,有两个位置可以进行assetbundle ...

  6. Unity3D — — UGUI之RectTransform

    Mask.GetComponent<RectTransform>().anchoredPosition(子物体) = hotKey_image.rectTransform.anchored ...

  7. jmeter阶梯加压线程组

    添加阶梯加压线程组路径为鼠标捕获测试计划后,点击鼠标右键->添加->Threads(Users)->jp@gc – Stepping Thread Group(deprecated) ...

  8. mac指令备忘

    在这里简单记录下最近使用的快捷键,备忘,随时更新. 简单指令记录 mkdir 创建路径 pwd 输出当前路径 ls 查看目录 cd touch 创建文件 tree 输出目录树 mv 源文件 目标文件或 ...

  9. leetcode第217.题存在重复元素

    1.题目描述 给定一个整数数组,判断是否存在重复元素. 如果任何值在数组中出现至少两次,函数返回 true.如果数组中每个元素都不相同,则返回 false. 2.示例 2.1 输入: [1,2,3,1 ...

  10. 哪些场景下无法获得上一页referrer信息

    哪些场景下无法获得上一页referrer信息 直接在浏览器地址栏中输入地址: 使用 location.reload() 刷新(location.href 或者  location.replace()  ...