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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM