QVariant,被称为万能数据类型,实际上它是类似C++的联合union类型。简单的说自定义性能强就像一个盒子几乎可以让你放任意的qt类型,同时可以轻松构造任意类型的任意复杂数据结构,但请注意复杂类型意味着性能和效率的让步。
qt6在文档中如下描述:
由于C++禁止联合union包含具有非默认构造函数或析构函数的类型,这会导致好多继承的类qt类不能在联合中使用。如果没有 QVariant,这对 QObject::property()和数据库工作等来说将是一个问题,故引入该类型。
一、为什么要有QVariant类型
经过测试实际上是“联合体中的成员对象不允许有自定义构造函数”
//以下代码报错
#include <iostream>
class Greeting {
int a;
char b;
Greeting (){}
};
typedef union _uni {
Greeting s;
}uni;
int main(void)
{
uni u;
return 0;
}
二、QVariant支持常见类型
注意:Type type(),已经在qt6中被移除,*.type()已经无法使用,可用*.typeName()输出类型名称;
它几乎支持常见的qt中所有类型,在使用过程中就可以轻松的保存很多类型的值,有点类似盒子,尽管放就行。
QVariant str1("让世界爱上中国造!");
if(str1.canConvert<QString>())
{
qDebug()<<"str1 is QString type";
}
qDebug()<<"str1 tostring type="<<str1.toString();
qDebug()<<"str1 to int type="<<str1.toInt();
QList<int> intList = {7, 11, 42};
QVariant variant = QVariant::fromValue(intList);
if (variant.canConvert<QVariantList>())
{
QSequentialIterable iterable = variant.value<QSequentialIterable>();
QSequentialIterable::const_iterator it = iterable.begin();
const QSequentialIterable::const_iterator end = iterable.end();
for ( ; it != end; ++it) {
qDebug() << *it;
}
}
如上图,使用的时候一般使用canConvert<类型名>() 判断能不能转为该类型,也可以调相应的转换函数toInt()直接转换输出,转化失败则为0;
三、QVariant支持的自定义类型
以前自定义需要Q_DECLARE_METATYPE去注册,现在也不需要了;
总结,QVariant非常的灵活既能支持已有类型还能支持自定义类型,但任意类型的任意复杂数据结构意味着性能和效率的让步。