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

Posted 朝闻道

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QVariant相当于一个包含大多数Qt数据类型的联合体(源码解读)相关的知识,希望对你有一定的参考价值。

将数据存储为一个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数据类型的联合体(源码解读)的主要内容,如果未能解决你的问题,请参考以下文章

Qt的QVariant类

自定义数据类型使用QVariant转换的方法

QVariant类

如何在Qt中使用自定义数据类型

Qt - 没有匹配函数调用‘QVariant::QVariant(MyClass&)’

QVariant 中的自定义类型转换为空字符串