QVariant自定义类型例子及机制分析

QVariant使用自定义类型的例子

#include <QCoreApplication>
#include <QVariant>
#include <QString>
#include <QDebug>

void Test();

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Test();
    return a.exec();
}

class Cup
{
 public:
    QString material;
};

Q_DECLARE_METATYPE(Cup)

void Test()
{
    Cup cup1;
    cup1.material = "steel";

    QVariant q1;
    q1.setValue(cup1);

    //内部复制cup1对象,复制的对象为堆对象,保存在d->data.shared中
    //d->is_shared = true;
    //d->data.shared = new QVariant::PrivateShared(ptr);

    //const void *QVariant::constData() const
    //{
    //    return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.ptr);
    //}

    //template<typename T>
    //inline T value() const
    //{ return qvariant_cast<T>(*this); }
    //qvariant_cast函数最终调用 constData函数获得之前复制的对象的指针,再转变成T类型的实例

    Cup cup2 = q1.value<Cup>();

    qDebug()<<cup2.material;
}


QVariant保存用户类型的机制的源码分析如下,源码版本为你5.3。

template<typename T>

inline void QVariant::setValue(const T &avalue)

{ qVariantSetValue(*this, avalue); }

 

template <typename T>

inline void qVariantSetValue(QVariant &v, const T &t)

{

    //if possible we reuse the current QVariant private

    const uint type = qMetaTypeId<T>();

    QVariant::Private &d = v.data_ptr();

    if (v.isDetached() && (type == d.type || (type <= uint(QVariant::Char) && d.type <= uint(QVariant::Char)))) {

.........

    } else {

        v = QVariant(type, &t, QTypeInfo<T>::isPointer); //进入此分支

    }

}

 

 

template <typename T>

inline Q_DECL_CONSTEXPR int qMetaTypeId()

{

    Q_STATIC_ASSERT_X(QMetaTypeId2<T>::Defined, "Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system");

    return QMetaTypeId2<T>::qt_metatype_id();

}

 

template <typename T>

struct QMetaTypeId2

{

    enum { Defined = QMetaTypeId<T>::Defined, IsBuiltIn=false };

static inline Q_DECL_CONSTEXPR int qt_metatype_id() 

{ return QMetaTypeId<T>::qt_metatype_id(); }

};

 

#define Q_DECLARE_METATYPE(TYPE) Q_DECLARE_METATYPE_IMPL(TYPE)

#define Q_DECLARE_METATYPE_IMPL(TYPE)                                   \

    QT_BEGIN_NAMESPACE                                                  \

    template <>                                                         \

    struct QMetaTypeId< TYPE >                                          \

    {                                                                   \

        enum { Defined = 1 };                                           \

        static int qt_metatype_id()                                     \

            {                                                           \

                static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \

                if (const int id = metatype_id.loadAcquire())           \

                    return id;   

//调用qRegisterMetaType注册用户自定义的类型                                       \

                const int newId = qRegisterMetaTypeTYPE >(#TYPE,      \

                              reinterpret_cast< TYPE *>(quintptr(-1))); \

                metatype_id.storeRelease(newId);                        \

                return newId;                                           \

            }                                                           \

    };                                                                  \

QT_END_NAMESPACE

 

template <typename T>

int qRegisterMetaType(const char *typeName

#ifndef Q_QDOC

    , T * dummy = 0

    , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType defined = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined

#endif

)

{

#ifdef QT_NO_QOBJECT

    QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = typeName; //const char *转换成字节数组

#else

    QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);

#endif

    return qRegisterNormalizedMetaType<T>(normalizedTypeName, dummy, defined);

}

 

 

 

 

template <typename T>

int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName

#ifndef Q_QDOC

    , T * dummy = 0

    , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType defined = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined

#endif

)

{

.........

//QMetaTypeFunctionHelper<T>实例化了要注册类型对应的QMetaTypeFunctionHelper

//通过此类包装,获得TYPE类的对应的Delete等函数

    const int id = QMetaType::registerNormalizedType(normalizedTypeName,

                                   QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Delete,

                                   QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Create,

                                   QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Destruct,

                                   QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Construct,

                                   int(sizeof(T)),

                                   flags,

                                   QtPrivate::MetaObjectForType<T>::value());

 

    if (id > 0) {

        QtPrivate::SequentialContainerConverterHelper<T>::registerConverter(id);

        QtPrivate::AssociativeContainerConverterHelper<T>::registerConverter(id);

        QtPrivate::MetaTypePairHelper<T>::registerConverter(id);

        QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter(id);

    }

 

    return id;

}

 

 

int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, Deleter deleter,

                            Creator creator,

                            Destructor destructor,

                            Constructor constructor,

                            int size, TypeFlags flags, const QMetaObject *metaObject)

{

    //<普通的参数合法性检查>

    QVector<QCustomTypeInfo> *ct = customTypes();

    if (!ct || normalizedTypeName.isEmpty() || !deleter || !creator || !destructor || !constructor)

        return -1;

    //</普通的参数合法性检查>

 

    //查找内建的支持的类型

    //自定义的类型名normalizedTypeName.constData()

    //自定义的类型名的字符串长度normalizedTypeName.size()

    int idx = qMetaTypeStaticType(normalizedTypeName.constData(),

                                  normalizedTypeName.size());

 

    int previousSize = 0;

    int previousFlags = 0;

    //用户自定义类型 进入此if

    if (idx == UnknownType) {

        QWriteLocker locker(customTypesLock());

        //在自定义类型中查找 看是否注册过

        idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),

                                           normalizedTypeName.size());

 

        if (idx == UnknownType) {//未注册过 所以注册

            QCustomTypeInfo inf;

            inf.typeName = normalizedTypeName;

            inf.creator = creator;

            inf.deleter = deleter;

#ifndef QT_NO_DATASTREAM

            inf.loadOp = 0;

            inf.saveOp = 0;

#endif

            inf.alias = -1;

            inf.constructor = constructor;

            inf.destructor = destructor;

            inf.size = size;

            inf.flags = flags;

            inf.metaObject = metaObject;

            idx = ct->size() + User;

            ct->append(inf); //完成注册

            return idx;

        }

 

        if (idx >= User) {

            previousSize = ct->at(idx - User).size;

            previousFlags = ct->at(idx - User).flags;

        }

    }

 

    .........

 

    return idx;

}

 

 

namespace QtMetaTypePrivate {

template <typename T, bool Accepted = true>

struct QMetaTypeFunctionHelper {

    static void Delete(void *t)

    {

        delete static_cast<T*>(t);

    }

 

    static void *Create(const void *t)

    {

        if (t)

            return new T(*static_cast<const T*>(t));

        return new T();

    }

 

    static void Destruct(void *t)

    {

        Q_UNUSED(t) // Silence MSVC that warns for POD types.

        static_cast<T*>(t)->~T();

    }

 

    static void *Construct(void *where, const void *t)

    {

        if (t)

            return new (where) T(*static_cast<const T*>(t));

        return new (where) T;

    }

//.........

};

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值