Qt 序列化对象

Qt中序列化数据用的类是QDataStream,但这个类只能序列化基本类型和一部分Qt定义的类,对于自定义类需要自己编写序列化函数。
在自定义类中声明友元函数,并实现:
class CKDrawBase:
{
public: 
    friend QDataStream & operator << (QDataStream &dataStream, CKDrawBase &drawBase);
    friend QDataStream & operator >> (QDataStream &dataStream, CKDrawBase &drawBase);
}
很显然,一个用于流出,一个用于流入。
 

对于一个简单类的序列化重载两个操作符即可,对一个多态类象这样声明:
class CKDrawBase:public QObject
{
Q_OBJECT
public:
    virtual void save(QDataStream &dataStream);
    virtual void load(QDataStream &dataStream);
    friend QDataStream & operator << (QDataStream &dataStream, CKDrawBase &drawBase);
    friend QDataStream & operator >> (QDataStream &dataStream, CKDrawBase **drawBase);
    //其他的成员
};
虚函数save()和load()分别用于实际流入流出的实现,由重载操作符函数调用,这样子类就无须实现重载操作符函数,只须根据需要重载save()和load()即可。
子类如下声明:
class CKDrawLine:public CKDrawBase
{
Q_OBJECT
public:
    void save(QDataStream &dataStream);
    void load(QDataStream &dataStream);
    //其他的成员  
};
class CKDrawRectangle:public CKDrawBase
{
Q_OBJECT
public:
    void save(QDataStream &dataStream);
    void load(QDataStream &dataStream);
    //其他的成员
};
重载<<函数实现:
friend QDataStream & operator << (QDataStream &dataStream, CKDrawBase &drawBase)
{
    dataStream << QString(drawBase.metaObject()->className());//将对象的类名写入流中
    drawBase.save(dataStream);
    return dataStream;
}
在函数中,首先将对象的类名写入流中,然后调入save()函数,实现具体的数据流入。

重载>>函数实现:
QDataStream & operator >> (QDataStream &dataStream, CKDrawBase **drawBase)
{
    QString str;
    dataStream >> str;
    *drawBase = NULL;
    if (str == QString("CKDrawLine"))   //根据类名字符串生成相应类的对象
    {
        *drawBase = new CKDrawLine;
        (*drawBase)->load(dataStream);
        return dataStream;
    }

    if (str == QString("CKDrawRectangle"))
    {
        *drawBase = new CKDrawRectangle;
        (*drawBase)->load(dataStream);
        return dataStream;
    }
    return dataStream;
}
在函数中,先读出保存的类名,然后根据相应的类名生成相应的对象,生成的对象指针保存在*drawBase中。

使用:
上述程序编写好后,就可以使用了。
例:
声明了一个QList对象QList drawList,要将其保存到文件中,或从文件中读出:
保存:
    dataStream << drawList.count();//dataStream为QdataStream类型。
    QList::const_iterator i;
    for (i=drawList.constBegin();i!=drawList.constEnd();++i)
    {
        dataStream << *(*i);
    }

读出:
    int count;
    CKDrawBase *ptr;
    dataStream >> count;     //dataStream为QdataStream类型。
    for (int i=0; i<count;++i)
    {
        dataStream >> &ptr;
        if (ptr != NULL)
        {
            drawList.append(ptr);
        }
    }

 
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt序列化(Serialization)功能允许你在程序之间或持久化存储中保存和恢复对象的状态。这是一项强大的工具,特别是在跨版本迁移或不同模块间传递数据时,能够保证数据的一致性和可读性。 **版本兼容性**在Qt序列化中是非常关键的。当你升级或改变应用程序的代码后,旧版本的程序可能无法读取新版本生成的数据,反之亦然。Qt提供了几种机制来处理版本兼容性: 1. **Qt Meta Object System (QMetaObject)**:使用QMetaObject可以创建具有不同版本的序列化数据的类。你可以设置元对象系统中的`Q_OBJECT`宏来启用序列化,并定义`Q_PROPERTY`来指定哪些属性需要被序列化。通过指定`Q_INVOKABLE`标志,函数也可以被序列化Qt会自动处理不同版本之间的属性更改。 2. **qRegisterMetaType()**: 这个函数用于注册特定类型的数据,以便于序列化。如果你在新版本中添加了新的数据类型,需要确保在旧版本中也注册,或者为旧版本提供一种方法来忽略新数据。 3. **QDataStream**和`QTextStream`:在更新过程中,如果数据结构发生变化,你可以定义一个策略来处理旧版本的数据,比如跳过未知字段,或者为新字段提供默认值。 4. **Qt Serializers**: Qt提供了一些预编译的序列化库,如QSettings、QByteArray等,它们有自己的方式处理版本差异,例如提供不同的文件格式或版本号标记。 **相关问题--:** 1. 如何确保Qt对象在不同版本间的序列化一致性? 2. 在更新Qt应用程序时,如何处理已有的QDataStream或QTextStream数据格式变化? 3. Qt的哪些类或工具可以帮助处理版本不兼容的序列化问题?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值