您的位置:首页 > 编程语言 > Qt开发

Qt中序列化对象

2016-06-08 15:30 447 查看
转自:http://blog.tianya.cn/blogger/post_show.asp?idWriter=0&Key=0&BlogID=53411&PostID=3573216

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);

        }

    }

说明:

1、使用多态的话,必须要从QObject继承,因为要保存类名字符串。

2、每增加一个子类,都要修改重载>>函数实现,以生成相应的对象。

3、还不知道有没有更好的办法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: