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

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 reserved36 #ifdef QT3_SUPPORT37         ColorGroup = 63,38 #endif39         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_SUPPORT66         IconSet = Icon,67         CString = ByteArray,68         PointArray = Polygon,69 #endif70         LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type71     };

 

数据类型转换:

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

技术分享

可通过成员函数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数据类型的联合体(源码解读)