qvariant是如何和稀泥的
Posted 论睡不着与不想睡的区别
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了qvariant是如何和稀泥的相关的知识,希望对你有一定的参考价值。
unionData
char c;
uchar uc;
short s;
signedchar sc;
ushort us;
int i;
uint u;
long l;
ulong ul;
bool b;
double d;
float f;
qreal real;
qlonglong ll;
qulonglong ull;
QObject *o;
void *ptr;
PrivateShared*shared;
;
QVariant介绍(来自Qt助手)
The QVariant class acts like a union for the most common Qt datatypes.
Because C++forbids unions from including types that have non-default constructors ordestructors, most interesting Qt classes cannot be used in unions. Without QVariant, this would be a problem for QObject::property() and for database work, etc.
QVariant类像是一个大部分Qt基础数据类型的联合体。由于C++的union类型不能包含无默认构造函数或析构函数的成员,导致大部分有用的Qt类不能放到union中。如果没有QVariant,QObject::property、数据库操作等将很难实现。
注:C++ union参考《C++ Primer 第五版》19.6节
问题
其实C++ 11已经可以将含有构造函数的复杂类型放入union中,在《C++ Primer 第五版》19.6节有使用类管理这种资源的例子。即使这样,QVariant仍然不能直接将所有需要管理的类型直接以放入union中,因为QVariant管理的Qt数据类型很多,而且未来也会扩展,已存在的类型也有可能扩展,这样QVariant占用的内存至少是它管理的最大的那个类型那么大,对于常用的基本数据类型来说,使用QVariant的代价就会变得特别大,而QVariant在Qt中属于比较核心的类,使用的地方太多,这显然不可行。那么实际上QVariant是怎么将各种数据类型和稀泥的呢?
思路
看了Qt助手里的介绍之后我还以为QVariant的实现不使用union。那就奇怪了,这么多类型放到一起,难道是void*加上类型转换实现的?看了Qt的源码之后发现其实里面使用了union,只是对基本数据类型和类类型做了区分,基本数据类型直接存值,类类型存指针,下面是这个union的定义:
细节
1.union Data中有三个成员是指针类型,QObject*o容易理解,当存储的是QObject类或子类类型的时候使用该成员,那么另外两个指针的作用是什么?
2.有三个成员是指针类型,那么对象真正的存储位置在哪,是动态分配?如果是动态分配,QVariant是如何管理这些资源的?
3.QVariant中有QVariant::type()等与类型判断有关的成员,并且在QVariant::toXXX转换失败时返回空对象或者不合法的对象,所以QVariant应该存储了值的类型信息。
实现
首先看一下QVariant的构造函数列表
class QVariant
public:
QVariant() noexcept : d()
~QVariant();
QVariant(Type type);
QVariant(int typeId, const void *copy);
QVariant(int typeId, const void *copy, uint flags);
QVariant(const QVariant &other);
QVariant(int i);
QVariant(uint ui);
QVariant(qlonglong ll);
QVariant(qulonglong ull);
QVariant(bool b);
QVariant(double d);
QVariant(float f);
QVariant(const char *str);
QVariant(const QByteArray &bytearray);
QVariant(const QBitArray &bitarray);
QVariant(const QString &string);
QVariant(QLatin1String string);
QVariant(const QStringList &stringlist);
QVariant(QChar qchar);
QVariant(const QDate &date);
QVariant(const QTime &time);
QVariant(const QDateTime &datetime);
QVariant(const QList<QVariant> &list);
QVariant(const QMap<QString,QVariant>&map);
QVariant(const QHash<QString,QVariant> &hash);
//geometry variant
QVariant(const QSize &size);
QVariant(const QSizeF &size);
QVariant(const QPoint &pt);
QVariant(const QPointF &pt);
QVariant(const QLine &line);
QVariant(const QLineF &line);
QVariant(const QRect &rect);
QVariant(const QRectF &rect);
QVariant(const QLocale &locale);
// regexp
QVariant(const QRegExp ®Exp);
//bootstrapped
QVariant(const QRegularExpression &re);
QVariant(const QUrl &url);
QVariant(const QEasingCurve &easing);
QVariant(const QUuid &uuid);
QVariant(const QModelIndex &modelIndex);
QVariant(const QPersistentModelIndex &modelIndex);
QVariant(const QJsonValue &jsonValue);
QVariant(const QJsonObject &jsonObject);
QVariant(const QJsonArray &jsonArray);
QVariant(const QJsonDocument &jsonDocument);
;
可以看到QVariant支持很多类型,从实现上分大概有两类:基本数据类型,类类型。但是所有的类类型都不是QObject子类,而且大部分没有父类。不同的基本数据类型或不同类类型实现相似,所以下面为了减少篇幅,本想列举部分实现,可是无非是各种类型判断和类型转换,不说了
以上是关于qvariant是如何和稀泥的的主要内容,如果未能解决你的问题,请参考以下文章
如何将 QVariant::fromValue 与 QString 一起使用?