找回密码
 注册
查看: 1621|回复: 0

在Qt中序列化对象

[复制链接]
发表于 2005-12-20 20:03:33 | 显示全部楼层 |阅读模式
前几天在论坛发了个帖子求助,无果,今天终于把这个问题解决啦 :D,贴出来,与大家共享,也希望能有朋友提出更好的办法

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

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

重载>>函数实现:
[code:1]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;
}[/code:1]在函数中,先读出保存的类名,然后根据相应的类名生成相应的对象,生成的对象指针保存在*drawBase中。

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

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

说明:
1、使用多态的话,必须要从QObject继承,因为要保存类名字符串。
2、每增加一个子类,都要修改重载>>函数实现,以生成相应的对象。
3、还不知道有没有更好的办法
您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2025-2-7 14:28 , Processed in 0.021615 second(s), 15 queries .

© 2001-2025 Discuz! Team. Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表