IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 关于使用QVariant和QDataStream进行序列化操作的介绍 -> 正文阅读

[C++知识库]关于使用QVariant和QDataStream进行序列化操作的介绍

1、关于序列化

百度词条:序列化(Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。

2、一些开源序列化工具

(1)Boost?的?serialization库

(2)谷歌的protobuf,官网地址:https://developers.google.cn/protocol-buffers/

(3)用于在C++结构体和json/xml之间互相转换的 XPACK? ? ? ? ?????????????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??????????????????github地址:https://github.com/xyz347/xpack

3、使用QVariant实现序列化

(1)利用 QVariant 、QVariantMap、QJsonDocument?实现序列化

Serializable.h

#pragma once
#include <QVariant>

/*
* 
* 可序列化基类,具体的类继承于它,可视为具有了可序列化的能力
* 
*/

class Serializable
{
public:
	virtual ~Serializable() {}

	/*
	* 转化为 QVariant 类型
	*/
	virtual QVariant toVariant() const = 0;

	/*
	* 从 QVariant 类型转为具体的数据
	*/
	virtual void fromVariant(const QVariant& variant) = 0;
};

Serializer.h

#pragma once
#include <QString>

#include "Serializable.h"

/*
* 
* 抽象的序列化类,通过继承此类,可以拓展为 Json,xml,等格式
* 
*/

class Serializer
{
public:
	virtual ~Serializer() {}


	/*
	* 将可序列化的内容保存至文件中
	*/
	virtual void save(const Serializable& serializable, const QString& filepath, const QString& rootName = "") = 0;

	/*
	* 从文件中加载可序列化的内容
	*/
	virtual void load(Serializable& serializable, const QString& filepath) = 0;
};

JsonSerializer.h

#pragma once

#include "Serializer.h"

class JsonSerializer : public Serializer
{
public:
	JsonSerializer();

	void save(const Serializable& serializable, const QString& filepath, const QString& rootName = "") override;

	void load(Serializable& serializable, const QString& filepath) override;
};

JsonSerializer.cpp

#include "JsonSerializer.h"

#include <QJsonDocument>
#include <QFile>

JsonSerializer::JsonSerializer() :
    Serializer()
{
}

void JsonSerializer::save(const Serializable& serializable, const QString& filepath, const QString& /*rootName*/)
{
    QJsonDocument doc = QJsonDocument::fromVariant(serializable.toVariant());
    QFile file(filepath);
    file.open(QFile::WriteOnly);
    file.write(doc.toJson());
    file.close();
}

void JsonSerializer::load(Serializable& serializable, const QString& filepath)
{
    QFile file(filepath);
    file.open(QFile::ReadOnly);
    QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
    file.close();
    serializable.fromVariant(doc.toVariant());
}

(2)使用

#include <QtCore/QCoreApplication>

#include "Serializer.h"
#include "JsonSerializer.h"


struct MyData : public Serializable 
{
    QString name;
    int age;

    QVariant toVariant() const
    {
        QVariantMap map;
        map.insert("name", name);
        map.insert("age", age);
        return map;
    }

    void fromVariant(const QVariant& variant)
    {
        QVariantMap map = variant.toMap();
        name = map.value("name").toString();
        age = map.value("age").toInt();
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    MyData data;
    data.age = 18;
    data.name = QStringLiteral("张三");

    //【1】
    JsonSerializer serializer;
    serializer.save(data, "file.dat");

    //【2】
    MyData data2;
    serializer.load(data2, "file.dat");

    return a.exec();
}

4、使用QDataStream实现序列化

(1)在Qt助手里面搜索 Serializing Qt Data Types 查看支持序列化的类型,QPixmap,QImage,QVector,QMap等类型都是支持序列化操作的

(2)自定义结构体序列化示例

#include <QtCore/QCoreApplication>
#include <QString>
#include <QDataStream>
#include <QVector>
#include <QMap>
#include <QVariant>
#include <QByteArray>



struct MyData
{
    QString name;
    int value;

    /*
    * out
    */
    friend QDataStream& operator << (QDataStream& stream, const MyData& d)
    {
        stream << d.name << d.value;
        return stream; 
    }
        
    /*
    * in
    */
    friend QDataStream& operator >>(QDataStream& stream, MyData& d)
    {
        stream >> d.name >> d.value; 
        return stream; 
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    MyData data{ "example", 1};

    QByteArray ba;

    /*
    * serialize
    */
    QDataStream out(&ba, QIODevice::WriteOnly);
    out << data;

    /*
    * deserialize
    */
    QDataStream in(&ba, QIODevice::ReadOnly);
    MyData data2;
    while (!in.atEnd()) {
        in >> data2;
    }


    return a.exec();
}

(3)如上代码所示,自定义结构体需要重载实现<<?和 >>?操作符,可放置在结构体外实现如下定义:

QDataStream &operator<<(QDataStream &, const QXxx &);

QDataStream &operator>>(QDataStream &, QXxx &);

如果要放在结构体内部实现重载,则需在函数前加上?friend?关键字。

(4)观察这2个重载操作符,行为几乎一致,但是上面的写法太过于繁琐,每次定义一个结构体就需要重新写一遍,参考XPACK里面对于宏定义的使用,可利用 __VA_ARGS__?定义下列宏来对结构体参数打包:

#pragma once

#define STREAM_O <<
#define STREAM_I >>
#define P_PACK_EXPAND(...) __VA_ARGS__
#define P_PACK_COUNT(LEVEL, _99,_98,_97,_96,_95,_94,_93,_92,_91,_90,_89,_88,_87,_86,_85,_84,_83,_82,_81,_80,_79,_78,_77,_76,_75,_74,_73,_72,_71,_70,_69,_68,_67,_66,_65,_64,_63,_62,_61,_60,_59,_58,_57,_56,_55,_54,_53,_52,_51,_50,_49,_48,_47,_46,_45,_44,_43,_42,_41,_40,_39,_38,_37,_36,_35,_34,_33,_32,_31,_30,_29,_28,_27,_26,_25,_24,_23,_22,_21,_20,_19,_18,_17,_16,_15,_14,_13,_12,_11,_10,_9,_8,_7,_6,_5,_4,_3,_2,_1,N,...) LEVEL##N
#define P_PACK_N(LEVEL,ACTION, ...)  P_PACK_EXPAND(P_PACK_COUNT(LEVEL, __VA_ARGS__,_99,_98,_97,_96,_95,_94,_93,_92,_91,_90,_89,_88,_87,_86,_85,_84,_83,_82,_81,_80,_79,_78,_77,_76,_75,_74,_73,_72,_71,_70,_69,_68,_67,_66,_65,_64,_63,_62,_61,_60,_59,_58,_57,_56,_55,_54,_53,_52,_51,_50,_49,_48,_47,_46,_45,_44,_43,_42,_41,_40,_39,_38,_37,_36,_35,_34,_33,_32,_31,_30,_29,_28,_27,_26,_25,_24,_23,_22,_21,_20,_19,_18,_17,_16,_15,_14,_13,_12,_11,_10,_9,_8,_7,_6,_5,_4,_3,_2,_1))P_PACK_EXPAND((ACTION, __VA_ARGS__))
#define P_PACK(ACTION, ...)   P_PACK_N(PSTREAM, ACTION, __VA_ARGS__)

#define PSTREAM_1(ACTION,  A)        ACTION d.##A;
#define PSTREAM_2(ACTION,  A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_1(ACTION, __VA_ARGS__))
#define PSTREAM_3(ACTION,  A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_2(ACTION, __VA_ARGS__))
#define PSTREAM_4(ACTION,  A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_3(ACTION, __VA_ARGS__))
#define PSTREAM_5(ACTION,  A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_4(ACTION, __VA_ARGS__))
#define PSTREAM_6(ACTION,  A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_5(ACTION, __VA_ARGS__))
#define PSTREAM_7(ACTION,  A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_6(ACTION, __VA_ARGS__))
#define PSTREAM_8(ACTION,  A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_7(ACTION, __VA_ARGS__))
#define PSTREAM_9(ACTION,  A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_8(ACTION, __VA_ARGS__))
#define PSTREAM_10(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_9(ACTION, __VA_ARGS__))
#define PSTREAM_11(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_10(ACTION, __VA_ARGS__))
#define PSTREAM_12(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_11(ACTION, __VA_ARGS__))
#define PSTREAM_13(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_12(ACTION, __VA_ARGS__))
#define PSTREAM_14(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_13(ACTION, __VA_ARGS__))
#define PSTREAM_15(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_14(ACTION, __VA_ARGS__))
#define PSTREAM_16(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_15(ACTION, __VA_ARGS__))
#define PSTREAM_17(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_16(ACTION, __VA_ARGS__))
#define PSTREAM_18(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_17(ACTION, __VA_ARGS__))
#define PSTREAM_19(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_18(ACTION, __VA_ARGS__))
#define PSTREAM_20(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_19(ACTION, __VA_ARGS__))
#define PSTREAM_21(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_20(ACTION, __VA_ARGS__))
#define PSTREAM_22(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_21(ACTION, __VA_ARGS__))
#define PSTREAM_23(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_22(ACTION, __VA_ARGS__))
#define PSTREAM_24(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_23(ACTION, __VA_ARGS__))
#define PSTREAM_25(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_24(ACTION, __VA_ARGS__))
#define PSTREAM_26(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_25(ACTION, __VA_ARGS__))
#define PSTREAM_27(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_26(ACTION, __VA_ARGS__))
#define PSTREAM_28(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_27(ACTION, __VA_ARGS__))
#define PSTREAM_29(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_28(ACTION, __VA_ARGS__))
#define PSTREAM_30(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_29(ACTION, __VA_ARGS__))
#define PSTREAM_31(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_30(ACTION, __VA_ARGS__))
#define PSTREAM_32(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_31(ACTION, __VA_ARGS__))
#define PSTREAM_33(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_32(ACTION, __VA_ARGS__))
#define PSTREAM_34(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_33(ACTION, __VA_ARGS__))
#define PSTREAM_35(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_34(ACTION, __VA_ARGS__))
#define PSTREAM_36(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_35(ACTION, __VA_ARGS__))
#define PSTREAM_37(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_36(ACTION, __VA_ARGS__))
#define PSTREAM_38(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_37(ACTION, __VA_ARGS__))
#define PSTREAM_39(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_38(ACTION, __VA_ARGS__))
#define PSTREAM_40(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_39(ACTION, __VA_ARGS__))
#define PSTREAM_41(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_40(ACTION, __VA_ARGS__))
#define PSTREAM_42(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_41(ACTION, __VA_ARGS__))
#define PSTREAM_43(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_42(ACTION, __VA_ARGS__))
#define PSTREAM_44(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_43(ACTION, __VA_ARGS__))
#define PSTREAM_45(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_44(ACTION, __VA_ARGS__))
#define PSTREAM_46(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_45(ACTION, __VA_ARGS__))
#define PSTREAM_47(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_46(ACTION, __VA_ARGS__))
#define PSTREAM_48(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_47(ACTION, __VA_ARGS__))
#define PSTREAM_49(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_48(ACTION, __VA_ARGS__))
#define PSTREAM_50(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_49(ACTION, __VA_ARGS__))
#define PSTREAM_51(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_50(ACTION, __VA_ARGS__))
#define PSTREAM_52(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_51(ACTION, __VA_ARGS__))
#define PSTREAM_53(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_52(ACTION, __VA_ARGS__))
#define PSTREAM_54(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_53(ACTION, __VA_ARGS__))
#define PSTREAM_55(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_54(ACTION, __VA_ARGS__))
#define PSTREAM_56(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_55(ACTION, __VA_ARGS__))
#define PSTREAM_57(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_56(ACTION, __VA_ARGS__))
#define PSTREAM_58(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_57(ACTION, __VA_ARGS__))
#define PSTREAM_59(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_58(ACTION, __VA_ARGS__))
#define PSTREAM_60(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_59(ACTION, __VA_ARGS__))
#define PSTREAM_61(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_60(ACTION, __VA_ARGS__))
#define PSTREAM_62(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_61(ACTION, __VA_ARGS__))
#define PSTREAM_63(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_62(ACTION, __VA_ARGS__))
#define PSTREAM_64(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_63(ACTION, __VA_ARGS__))
#define PSTREAM_65(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_64(ACTION, __VA_ARGS__))
#define PSTREAM_66(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_65(ACTION, __VA_ARGS__))
#define PSTREAM_67(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_66(ACTION, __VA_ARGS__))
#define PSTREAM_68(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_67(ACTION, __VA_ARGS__))
#define PSTREAM_69(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_68(ACTION, __VA_ARGS__))
#define PSTREAM_70(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_69(ACTION, __VA_ARGS__))
#define PSTREAM_71(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_70(ACTION, __VA_ARGS__))
#define PSTREAM_72(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_71(ACTION, __VA_ARGS__))
#define PSTREAM_73(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_72(ACTION, __VA_ARGS__))
#define PSTREAM_74(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_73(ACTION, __VA_ARGS__))
#define PSTREAM_75(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_74(ACTION, __VA_ARGS__))
#define PSTREAM_76(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_75(ACTION, __VA_ARGS__))
#define PSTREAM_77(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_76(ACTION, __VA_ARGS__))
#define PSTREAM_78(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_77(ACTION, __VA_ARGS__))
#define PSTREAM_79(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_78(ACTION, __VA_ARGS__))
#define PSTREAM_80(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_79(ACTION, __VA_ARGS__))
#define PSTREAM_81(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_80(ACTION, __VA_ARGS__))
#define PSTREAM_82(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_81(ACTION, __VA_ARGS__))
#define PSTREAM_83(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_82(ACTION, __VA_ARGS__))
#define PSTREAM_84(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_83(ACTION, __VA_ARGS__))
#define PSTREAM_85(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_84(ACTION, __VA_ARGS__))
#define PSTREAM_86(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_85(ACTION, __VA_ARGS__))
#define PSTREAM_87(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_86(ACTION, __VA_ARGS__))
#define PSTREAM_88(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_87(ACTION, __VA_ARGS__))
#define PSTREAM_89(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_88(ACTION, __VA_ARGS__))
#define PSTREAM_90(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_89(ACTION, __VA_ARGS__))
#define PSTREAM_91(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_90(ACTION, __VA_ARGS__))
#define PSTREAM_92(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_91(ACTION, __VA_ARGS__))
#define PSTREAM_93(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_92(ACTION, __VA_ARGS__))
#define PSTREAM_94(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_93(ACTION, __VA_ARGS__))
#define PSTREAM_95(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_94(ACTION, __VA_ARGS__))
#define PSTREAM_96(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_95(ACTION, __VA_ARGS__))
#define PSTREAM_97(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_96(ACTION, __VA_ARGS__))
#define PSTREAM_98(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_97(ACTION, __VA_ARGS__))
#define PSTREAM_99(ACTION, A, ...)	 ACTION d.##A  P_PACK_EXPAND(PSTREAM_98(ACTION, __VA_ARGS__))



#define QPACK(T, ...)\
friend QDataStream& operator<< (QDataStream& stream, const T& d)\
{\
    stream P_PACK_EXPAND(P_PACK(STREAM_O, __VA_ARGS__));\
    return stream;\
}\
\
friend QDataStream& operator>> (QDataStream& stream, T& d)\
{\
    stream P_PACK_EXPAND(P_PACK(STREAM_I, __VA_ARGS__));\
    return stream;\
}

(5)接下来就可以使用定义好的 QPACK?宏来改造我们之前的结构体:

#include <QtCore/QCoreApplication>
#include <QString>
#include <QDataStream>
#include <QVector>
#include <QMap>
#include <QVariant>
#include <QByteArray>



struct MyData
{
    QString name;
    int value;

    QPACK(MyData, name, value);
};

struct MyData2
{
    QVector vec;
    qint32 value;
    qint32 value2;
    QString name;

    QPACK(MyData2, vec, value, value2, name);
};

struct MyData3
{
    QMap<int, int> map;

    QPACK(MyData3, map);
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    MyData data{ "example", 1};

    QByteArray ba;

    /*
    * serialize
    */
    QDataStream out(&ba, QIODevice::WriteOnly);
    out << data;

    /*
    * deserialize
    */
    QDataStream in(&ba, QIODevice::ReadOnly);
    MyData data2;
    while (!in.atEnd()) {
        in >> data2;
    }


    return a.exec();
}

(6)关于宏定义的说明

__VA_ARGS__ 作为参数传递给另一个宏时会被当成一个普通的参数,需要用一个宏展开来包裹一下 (即以上宏代码中的 P_PACK_EXPAND)

P_PACK_COUNT 和 P_PACK_N 搭配使用来确定元素个数,为便于理解其工作原理,可简化如下:


#include <iostream>

#define P_PACK_EXPAND(...) __VA_ARGS__
#define P_PACK_COUNT(_5,_4,_3,_2,_1,N,...) N
#define P_PACK_N(...)  P_PACK_EXPAND(P_PACK_COUNT(__VA_ARGS__,_5,_4,_3,_2,_1)) 

int main()
{
    
    /*
    *  P_PACK_N(1, 2, 3) 可看为
    * 
    * 
    * P_PACK_COUNT(_5,_4,_3,_2,_1, N,...)
    *                              |
    *     P_PACK_N( 1, 2, 3,_5,_4,_3,_2,_1)
    * 
    * 
    */

    P_PACK_N(1, 2, 3); // _3


    return 0;
}

源代码:https://download.csdn.net/download/pzywinner/20966625

 

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章           查看所有文章
加:2021-08-11 11:59:07  更:2021-08-11 12:06:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 9:55:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码