【零基础学QT】【031】C++中的union联合体和Qt中的QVariant

阅读: 评论:0

【零基础学QT】【031】C++中的union联合体和Qt中的QVariant

【零基础学QT】【031】C++中的union联合体和Qt中的QVariant

union联合体
union允许多种不同类型的数据共享同一块内存区域,并根据实际内存字节来获取指定类型的数据

//union乍一看和struct的结构很像,但是它的实际功能是和struct完全不一样的//union的字段并不是共存的,而是共享同一块内存,内存大小就是最长字段的长度//以UData为例,其长度就是st的长度,如果我们给st赋了值,那么st的第一个字节存放x,第二个字节存放y,第三个字节存放z//虽然我们没有给a,b,c赋值,但是由于内存是共享的,如果我们去获取a,那么就会将u的第一个字节作为整型数据返回,实际就是x的值//如果我们去获取d,那么就以u的前两个字节作为整型数据返回,即x和y的联合字节数据作为d//由于int的数据长度是和机器有关的,为了方便观察数值,这里故意使用了uint8_t和uint16_t,它们分别占一个字节和两个字节,char和bool占一个字节//从以上特征我们可以知道,union是不适合作为类来使用的,因为内存是共享的,给一个字段赋值就等于覆盖了其它字段的数值//union的意义在于,它可以用一个变量来存储多种不同类型的数据,并且不需要转型就可以轻松访问//union的本质是将内存字节视为任意类型的数据来访问,而不是将某块内存视为某个固定类型的字段//由于其内存共享性,在类型转换,字节处理方面,运用合理有时能起到巧妙的效果union UData {int8_t a;char b;bool c;int16_t d;struct ST {int8_t x;int8_t y;int8_t z;} st;};int main(int argc, char* argv[]) {UData u;//给st赋值,观察abcd变化u.st.x = 1;u.st.y = 2;u.st.z = 3;cout << unsigned(u.a) << endl;cout << unsigned(u.b) << endl;cout << u.c << endl;cout << unsigned(u.d) << endl;cout << unsigned(u.st.x) << unsigned(u.st.y) << unsigned(u.st.z) << endl << endl;//给a赋值,观察st和bcd变化u.a = 4;cout << unsigned(u.a) << endl;cout << unsigned(u.b) << endl;cout << u.c << endl;cout << unsigned(u.d) << endl;cout << unsigned(u.st.x) << unsigned(u.st.y) << unsigned(u.st.z) << endl;}

通过union来判断CPU是大端还小端
当我们的数据长度不止一个字节时,就要跨字节,占用多个存储器地址来存储,这就引出了存储顺序的问题
大端是指将数据的高字节部分,存放在存储器的低地址区域中
小端是指将数据的高字节部分,存放在存储器的高地址区域中
我们在实际表示中,一般将内存区域从左到右,由低到高表示,而数值表示,比如0x0FEE,则是将高字节显示在左边
显然大端模式更适合我们的阅读习惯,而小端则更适合CPU运算,高字节权重更高,显然更符合运算逻辑
现在我们通过union来测试CPU的大小端模式,这也是一道经典的面试题

union U {char a[4];int32_t b;} u { 'L', 'X', 'X', 'B' };//用宏记录CPU大小端模式//C语言int转char,是直接阶段高地址部分//所以如果是小端模式,留下的就是L,大端则是B#define ENDIAN (char) u.bint main(int argc, char* argv[]) {cout << u.a << endl;cout << u.b << endl;cout << ENDIAN << endl;}

QVariant
QVariant是对union的一种封装和简化,省去了我们自己去定义union联合体的步骤
QVariant和union一样,用于存储多种类型的数据
QVariant包含了一个union和type字段,union字段可以存储不同类型的数据,type可以记录实际数据的类型
QVariant默认支持基础类型和Qt常用类型,自定义类需要通过Q_DECLARE_METATYPE来声明,这样Moc编译器就会自动让union支持这个类型

//自定义类型class User {public:int id;string name;};//注册User和User*为元类型Q_DECLARE_METATYPE(User)Q_DECLARE_METATYPE(User *)int main(int argc, char *argv[]) {QVariant variant;//保存整数variant.setValue(12);cout << Int() << endl;cout << String().toStdString() << endl;//保存字符串variant.setValue(QString("hello"));cout << String().toStdString() << endl;//保存对象variant.setValue(User { 1, "A" });if (variant.canConvert<User>()) {User user = variant.value<User>();cout << user.name << endl;}//保存指针QVariant variant2 = QVariant::fromValue(new User { 2, "B" });if (variant2.canConvert<User *>()) {User *user = variant2.value<User *>();cout << user->name << endl;}//测试能否任意强转//对于canConvert=false的QVariant进行强转,将会返回指定类型的默认值//比如User*不能转为int,强转则返回0,User*不能转为QString,强转则返回空字符cout << variant2.canConvert<User *>() << endl;cout << variant2.canConvert<User>() << endl;cout << variant2.canConvert<int>() << endl;cout << variant2.canConvert<QString>() << endl;return 0;}

本文发布于:2024-02-02 07:24:20,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170682986242254.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:联合体   基础   QT   union   Qt
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23