QVariant实质
QVariant实质
为了达到这种目的,可以想象,该对象应该存储对象的类型信息,数据信息以及其他辅助详细
考虑用途,这种对象必须支持对不同对象的存储,对存储类型的检测以及取对象三个功能
1.对象的存储
代码见下:
QVariant(Type type);
QVariant(int typeOrUserType, const void *copy);
QVariant(int typeOrUserType, const void *copy, uint flags);
QVariant(const QVariant &other);
#ifndef QT_NO_DATASTREAM
QVariant(QDataStream &s);
#endif
QVariant(int i);
QVariant(uint ui);
QVariant(qlonglong ll);
QVariant(qulonglong ull);
QVariant(bool b);
QVariant(double d);
QVariant(float f) { d.is_null = false; d.type = QMetaType::Float; d.data.f = f; }
#ifndef QT_NO_CAST_FROM_ASCII
QT_ASCII_CAST_WARN_CONSTRUCTOR QVariant(const char *str);
#endif
QVariant(const QByteArray &bytearray);
QVariant(const QBitArray &bitarray);
QVariant(const QString &string);
QVariant(const QLatin1String &string);
QVariant(const QStringList &stringlist);
QVariant(const 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);
#ifndef QT_NO_GEOM_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);
#endif
QVariant(const QUrl &url);
QVariant(const QLocale &locale);
#ifndef QT_NO_REGEXP
QVariant(const QRegExp ®Exp);
#endif
#ifndef QT_BOOTSTRAPPED
QVariant(const QEasingCurve &easing);
#endif
QVariant(Qt::GlobalColor color);
在该对象中type负责记录对象的类型,这对于正确取出对象是很用得
3.成员函数
Type type() const;
int userType() const;
const char *typeName() const;
bool canConvert(Type t) const;
bool convert(Type t);
#ifdef QT3_SUPPORT
inline QT3_SUPPORT bool canCast(Type t) const
{ return canConvert(t); }
inline QT3_SUPPORT bool cast(Type t)
{ return convert(t); }
#endif
bool QVariant::canConvert(Type t) const
{
//we can treat floats as double
//the reason for not doing it the "proper" way is that QMetaType::Float's value is 135,
//which can't be handled by qCanConvertMatrix
//In addition QVariant::Type doesn't have a Float value, so we're using QMetaType::Float
const uint currentType = ((d.type == QMetaType::Float) ? QVariant::Double : d.type);
if (uint(t) == uint(QMetaType::Float)) t = QVariant::Double;
if (currentType == uint(t))
return true;
if (currentType > QVariant::LastCoreType || t > QVariant::LastCoreType) {
switch (uint(t)) {
case QVariant::Int:
return currentType == QVariant::KeySequence
|| currentType == QMetaType::ULong
|| currentType == QMetaType::Long
|| currentType == QMetaType::UShort
|| currentType == QMetaType::UChar
|| currentType == QMetaType::Char
|| currentType == QMetaType::Short;
case QVariant::Image:
return currentType == QVariant::Pixmap || currentType == QVariant::Bitmap;
case QVariant::Pixmap:
return currentType == QVariant::Image || currentType == QVariant::Bitmap
|| currentType == QVariant::Brush;
case QVariant::Bitmap:
return currentType == QVariant::Pixmap || currentType == QVariant::Image;
case QVariant::ByteArray:
return currentType == QVariant::Color;
case QVariant::String:
return currentType == QVariant::KeySequence || currentType == QVariant::Font
|| currentType == QVariant::Color;
case QVariant::KeySequence:
return currentType == QVariant::String || currentType == QVariant::Int;
case QVariant::Font:
return currentType == QVariant::String;
case QVariant::Color:
return currentType == QVariant::String || currentType == QVariant::ByteArray
|| currentType == QVariant::Brush;
case QVariant::Brush:
return currentType == QVariant::Color || currentType == QVariant::Pixmap;
case QMetaType::Long:
case QMetaType::Char:
case QMetaType::UChar:
case QMetaType::ULong:
case QMetaType::Short:
case QMetaType::UShort:
return qCanConvertMatrix[QVariant::Int] & (1 << currentType) || currentType == QVariant::Int;
default:
return false;
}
}
if(t == String && currentType == StringList)
return v_cast<QStringList>(&d)->count() == 1;
else
return qCanConvertMatrix[t] & (1 << currentType);
}
4.QVariant对象的最后一个主要的功能就是到给定类型的转换
函数簇如下:
int toInt(bool *ok = 0) const;
uint toUInt(bool *ok = 0) const;
qlonglong toLongLong(bool *ok = 0) const;
qulonglong toULongLong(bool *ok = 0) const;
bool toBool() const;
double toDouble(bool *ok = 0) const;
float toFloat(bool *ok = 0) const;
qreal toReal(bool *ok = 0) const;
QByteArray toByteArray() const;
QBitArray toBitArray() const;
QString toString() const;
QStringList toStringList() const;
QChar toChar() const;
QDate toDate() const;
QTime toTime() const;
QDateTime toDateTime() const;
QList<QVariant> toList() const;
QMap<QString, QVariant> toMap() const;
QHash<QString, QVariant> toHash() const;
/*!
\fn QTime QVariant::toTime() const
Returns the variant as a QTime if the variant has type() \l Time,
\l DateTime, or \l String; otherwise returns an invalid time.
If the type() is \l String, an invalid time will be returned if
the string cannot be parsed as a Qt::ISODate format time.
\sa canConvert(), convert()
*/
QTime QVariant::toTime() const
{
return qVariantToHelper<QTime>(d, Time, handler);
}
使用了模板函数:qVariantToHelper
5.关于qVariantToHelper
\fn bool QVariant::isValid() const
Returns true if the storage type of this variant is not
QVariant::Invalid; otherwise returns false.
*/
template <typename T>
inline T qVariantToHelper(const QVariant::Private &d, QVariant::Type t,
const QVariant::Handler *handler, T * = 0)
{
if (d.type == t)
return *v_cast<T>(&d);
T ret;
handler->convert(&d, t, &ret, 0);
return ret;
}
该函数根据对象信息和目标类型做转换工作,如果二者类型一致,则直接做转换,否则交给函数handler->convert处理
6.关于Handler对象
struct Handler {
f_construct construct;
f_clear clear;
f_null isNull;
#ifndef QT_NO_DATASTREAM
f_load load;
f_save save;
#endif
f_compare compare;
f_convert convert;
f_canConvert canConvert;
f_debugStream debugStream;
};
其实际结构为:
const QVariant::Handler qt_kernel_variant_handler = {
construct,
clear,
isNull,
#ifndef QT_NO_DATASTREAM
0,
0,
#endif
compare,
convert,
0,
#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
streamDebug
#else
0
#endif
};
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;
case QVariant::Char:
v_construct<QChar>(x, copy);
break;
case QVariant::StringList:
v_construct<QStringList>(x, copy);
break;
case QVariant::Map:
v_construct<QVariantMap>(x, copy);
break;
case QVariant::Hash:
v_construct<QVariantHash>(x, copy);
break;
case QVariant::List:
v_construct<QVariantList>(x, copy);
break;
case QVariant::Date:
v_construct<QDate>(x, copy);
break;
case QVariant::Time:
v_construct<QTime>(x, copy);
break;
case QVariant::DateTime:
v_construct<QDateTime>(x, copy);
break;
case QVariant::ByteArray:
v_construct<QByteArray>(x, copy);
break;
case QVariant::BitArray:
v_construct<QBitArray>(x, copy);
break;
#ifndef QT_NO_GEOM_VARIANT
case QVariant::Size:
v_construct<QSize>(x, copy);
break;
case QVariant::SizeF:
v_construct<QSizeF>(x, copy);
break;
case QVariant::Rect:
v_construct<QRect>(x, copy);
break;
case QVariant::LineF:
v_construct<QLineF>(x, copy);
break;
case QVariant::Line:
v_construct<QLine>(x, copy);
break;
case QVariant::RectF:
v_construct<QRectF>(x, copy);
break;
case QVariant::Point:
v_construct<QPoint>(x, copy);
break;
case QVariant::PointF:
v_construct<QPointF>(x, copy);
break;
#endif
case QVariant::Url:
v_construct<QUrl>(x, copy);
break;
case QVariant::Locale:
v_construct<QLocale>(x, copy);
break;
#ifndef QT_NO_REGEXP
case QVariant::RegExp:
v_construct<QRegExp>(x, copy);
break;
#endif
#ifndef QT_BOOTSTRAPPED
case QVariant::EasingCurve:
v_construct<QEasingCurve>(x, copy);
break;
#endif
case QVariant::Int:
x->data.i = copy ? *static_cast<const int *>(copy) : 0;
break;
case QVariant::UInt:
x->data.u = copy ? *static_cast<const uint *>(copy) : 0u;
break;
case QVariant::Bool:
x->data.b = copy ? *static_cast<const bool *>(copy) : false;
break;
case QVariant::Double:
x->data.d = copy ? *static_cast<const double*>(copy) : 0.0;
break;
case QMetaType::Float:
x->data.f = copy ? *static_cast<const float*>(copy) : 0.0f;
break;
case QMetaType::QObjectStar:
x->data.o = copy ? *static_cast<QObject *const*>(copy) : 0;
break;
case QVariant::LongLong:
x->data.ll = copy ? *static_cast<const qlonglong *>(copy) : Q_INT64_C(0);
break;
case QVariant::ULongLong:
x->data.ull = copy ? *static_cast<const qulonglong *>(copy) : Q_UINT64_C(0);
break;
case QVariant::Invalid:
case QVariant::UserType:
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;
}
该函数模板实现和平台有关,其中一个平台的实现如下:
template <class T>
inline void v_construct(QVariant::Private *x, const void *copy, T * = 0)
{
if (sizeof(T) > sizeof(QVariant::Private::Data)) {
x->data.shared = copy ? new QVariantPrivateSharedEx<T>(*static_cast<const T *>(copy))
: new QVariantPrivateSharedEx<T>;
x->is_shared = true;
} else {
if (copy)
new (&x->data.ptr) T(*static_cast<const T *>(copy));
else
new (&x->data.ptr) T;
}
}
QVariant大致就这个样子
QVariant实质的更多相关文章
- QVariant实质 (类似 C#中的装箱拆箱)
QVariant是一种可以存储不同类型的数据结构,在很多场合这是很有用得为了达到这种目的,可以想象,该对象应该存储对象的类型信息,数据信息以及其他辅助详细考虑用途,这种对象必须支持对不同对象的存储,对 ...
- C++中重定义的问题——问题的实质是声明和定义的关系以及分离式编译的原理
这里的问题实质是我们在头文件中直接定义全局变量或者函数,却分别在主函数和对应的cpp文件中包含了两次,于是在编译的时候这个变量或者函数被定义了两次,问题就出现了,因此,我们应该形成一种编码风格,即: ...
- 微信小程序实质是什么? Hybrid App
微信小程序是一种不需要下载安装即可使用的应用,用户扫一扫或者搜一下即可打开应用.微信小程序实质是Hybrid技术的应用.Hybrid App(混合模式移动应用). 小程序能够更多的可以更多的调用手机本 ...
- async/await的实质理解
async/await关键字能帮助开发者更容易地编写异步代码.但不少开发者对于这两个关键字的使用比较困惑,不知道该怎么使用.本文就async/await的实质作简单描述,以便大家能更清楚理解. 一.a ...
- QVariant与自定义数据类型转换的方法
在使用VC.Delphi编写用户界面程序的时候,经常会把对象与控件的data域进行绑定,便于程序运行中读写提高效率.然而在Qt编程中怎么实现这个功能呢?比如将一个用户自定义的结构体与QComboB ...
- QVariant类学习(非常强大的类型,甚至能处理QMap<QString ,QVariant>)
详细描述: QVariant类作为一个最为普遍的Qt数据类型的联合. 因为c++禁止没有构造函数和析构函数的联合体,许多继承的Qt类不能够在联合体当中使用.(联合体当中的变量共用一个存储区),没有了联 ...
- QVariant(相当于是Java里面的Object,起到一个数据类型“擦除”的作用,可以使用Q_DECLARE_METATYPE进行注册)
=QVariant= [%这个类型相当于是Java里面的Object,它把绝大多数Qt提供的数据类型都封装起来,起到一个数据类型“擦除”的作用.比如我们的 table单元格可以是string,也可以是 ...
- 董事长、总裁与CEO的区别与实质
自从信息产业兴起以来,尤其是网络股泡沫产生以来,“CEO”在中国骤然成为一个流行词汇.总经理和总裁们纷纷改称CEO,这个缩写词比它的中译版“首席执行官”更简洁,在中国人心目中更有神圣感,于是便出现了今 ...
- qsettings 保存自定义结构体(QVariant与自定义结构体相互转化)
参考博文:QVariant与自定义数据类型转换的方法. 这里摘取其关键内容: 1.将自定义数据类型使用Q_DECLARE_METATYPE宏进行声明,便于编译器识别. 2.在插入对象的时候,声明QVa ...
随机推荐
- Supervisor4.0和python2.7的crit问题,导致python进程阻塞
1.问题原因 Supervisor高版本在守护python2.7的服务时,会crit并报错并倒至进程阻塞(python进程存在,但不在运行)的问题,一般会和字符集有关系 <type 'excep ...
- nginx交替出现404和200
今天在调试接口的时候,发现一个奇怪的问题,服务器接口交替返回404和200错误. 排查的时候发现nginx下有大量的404错误记录,而tomcat有两个,一个有正常的访问记录,而另一个虽然启动正常,但 ...
- socket编程为什么需要htonl(), ntohl(), ntohs(),htons() 函数-------转载
在C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺序的问题.这是就可能用到htons(), ntohl(), ntohs(),htons()这4个函数. 网络字节顺序与本地字节顺序之间的转 ...
- 剑指offer-二维数组中的查找01
题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...
- 华为ensp使用
网络学习目录 AR是() Auto:自动线 copper:双绞线缆 serial:串行线 pos: 光纤 E1: ATM: CTL: STA: PC: MCS ...
- 微信小程序-----自定义验证码实现
这一段时间做小程序项目,使用的是mpvue的框架,需要自己实现验证码输入,模拟input的光标,上一个框输入后后一个框自动获取焦点,删除时从后往前依次删除.下图是整体效果: <template& ...
- Oracle 11g用exp无法导出空表的处理方法
Oracle 11G在用EXPORT导出时,空表不能导出. 11G中有个新特性,当表无数据时,不分配segment,以节省空间 解决方法: 1.insert一行,再rollback就产生segment ...
- sshpass 指定密码远程 ssh 到服务器 或者 scp 发送文件到服务器
在操作linux时,虽然可以对linux配置免秘钥登录,但是在配置免密码登录之前,是需要登录到其他节点主机的,这里提供一种类似ssh的方式,可以在命令后面加上相应的参数来设置你将要登录的远程主机的密码 ...
- Spark Streaming的使用——转载
转载自 Spark Streaming 使用
- c++ Dynamic Memory (part 2)
Don't use get to initialize or assign another smart pointer. The code that use the return from get c ...