我正在尝试使用QDataStream读/写我的自定义类。我已经重写了<<还有>>运算符,它们似乎可以很好地处理普通对象。但是,当我尝试将指针传递给自定义对象时,覆盖的操作符不能正常工作。
下面是来自card.h的相关数据:
#ifndef CARD_H
#define CARD_H
#include <QDataStream>
#include <QImage>
#include <QString>
class Card
{
private:
QString name;
QImage image;
QString type;
int strength;
int movement;
int deployCost;
QString back;
public:
Card();
QDataStream& read(QDataStream &dataStream);
QDataStream& write(QDataStream &dataStream) const;
...
};
QDataStream& operator <<(QDataStream &out, const Card &c);
QDataStream& operator >>(QDataStream &in, Card &c);
QDataStream& operator <<(QDataStream &out, const Card *c);
QDataStream& operator >>(QDataStream &in, Card *c);
//QDataStream& operator <<(QDataStream &out, const Card *&c);
//QDataStream& operator >>(QDataStream &in, Card *&c);
#endif // CARD_H
这里是card.cpp:
#include "card.h"
Card::Card()
{
}
QDataStream& operator <<(QDataStream &out, const Card &c) {
return c.write(out);
}
QDataStream& operator >>(QDataStream &in, Card &c) {
return c.read(in);
}
QDataStream& operator <<(QDataStream &out, const Card *c) {
return c->write(out);
}
QDataStream& operator >>(QDataStream &in, Card *c) {
return c->read(in);
}
/*QDataStream& operator <<(QDataStream &out, const Card *&c) {
return c->write(out);
}
QDataStream& operator >>(QDataStream &in, Card *&c) {
return c->read(in);
}*/
QDataStream& Card::read(QDataStream &dataStream) {
dataStream >> name;
dataStream >> image;
dataStream >> type;
dataStream >> strength;
dataStream >> movement;
dataStream >> deployCost;
dataStream >> back;
return dataStream;
}
QDataStream& Card::write(QDataStream &dataStream) const {
dataStream << name;
dataStream << image;
dataStream << type;
dataStream << strength;
dataStream << movement;
dataStream << deployCost;
dataStream << back;
return dataStream;
}
...
如你所见,我都试过了
QDataStream& operator <<(QDataStream &out, const Card *c);
QDataStream& operator >>(QDataStream &in, Card *c);
和
//QDataStream& operator <<(QDataStream &out, const Card *&c);
//QDataStream& operator >>(QDataStream &in, Card *&c);
如果我使用"Card *c",数据写得很好,但是当我试图读取时,我得到一个SEGFAULT。如果我使用"Card *&c",程序甚至不知道我已经覆盖了操作符,所以它不会被调用。
我做错了什么?
编辑:当我读取或写入"卡片"时,问题出现了,这是在deck.h中定义的QHash
QHash<QString, Card*> cards;
deck.h:
#ifndef DECK_H
#define DECK_H
#include <QDataStream>
#include <QHash>
#include "card.h"
class Deck
{
private:
QString name;
QHash<QString, Card*> cards;
public:
Deck();
QDataStream &read(QDataStream &dataStream);
QDataStream &write(QDataStream &dataStream) const;
...
};
QDataStream &operator<<(QDataStream &out, const Deck &d);
QDataStream &operator>>(QDataStream &in, Deck &d);
#endif // DECK_H
deck.cpp:
#include "deck.h"
Deck::Deck()
{
}
QDataStream &operator<<(QDataStream &out, const Deck &d) {
return d.write(out);
}
QDataStream &operator>>(QDataStream &in, Deck &d) {
return d.read(in);
}
QDataStream &Deck::read(QDataStream &dataStream) {
dataStream >> name;
// Reading the QHash - one problem spot
dataStream >> cards;
return dataStream;
}
QDataStream &Deck::write(QDataStream &dataStream) const {
dataStream << name;
// Writing the QHash - the other problem spot
dataStream << cards;
return dataStream;
}
...
因为卡片是作为指针存储在QHash中的,所以我不确定应该如何避免重写指针操作符。是否有更好的方法来读/写QHash,或*卡存储在QHash?
编辑:根据Marek R的回答,我寻找一种避免写卡片的方法*。解决方案是遍历QHash并保存每个单独的卡。
第一个问题是您正在尝试为指针执行此操作符。如果我的同事这么做,我可能会掐死他。在99.9999%的情况下,永远不要重载指针的操作符。
如果你坚持这样做,我猜你的代码使用这个操作符看起来像这样:
Card *uninitializedPointer;
someDataStream >> uninitializedPointer; // SEGFAULT
这是错误的,因为uninitializedPointer
是…它的名字说明了问题所在,您指的是受限或随机内存块。
也许你想要(这是错误的,但它会工作,我显示这个只是为了解释崩溃,而不是作为一个修复):
Card *initializedPointer = new Card;
someDataStream >> initializedPointer;
或:
Card object;
someDataStream >> &object;
不要试图通过在操作符中做分配来修复这个问题,否则你会在地狱里被炒菜:)只需将指针重载的操作符丢弃
流操作符的期望签名如下:
stream& operator<<(stream& out, const T& t);
stream& operator>>(stream& in, T& t);
参见如何正确重载<<ostream的操作符?或QDatastream operator>>QList<类*比;例如,>
这也适用于QDataStream。这里的困难在于T
是一个指针类型,但本质上你只是用指针类型代替T
。所以你的签名应该是:
QDataStream& operator<<(QDataStream &out, Card* const& c);
QDataStream& operator>>(QDataStream &in, Card*& c);
注意Card* const
中const
的位置,因为它是需要const的指针,而不是指针。