|
前几天在论坛发了个帖子求助,无果,今天终于把这个问题解决啦 :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、还不知道有没有更好的办法 ![](static/image/smiley/default/icon_cry.gif) |
|