问题
I am trying to read/write my custom classes using QDataStream. I have overridden the << and >> operators, which seem to work fine for normal objects. However, when I try to pass a pointer to my custom object, the overridden operators don't work properly.
Here is the relevant data from 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
And here is 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;
}
...
As you can see, I've tried both
QDataStream& operator <<(QDataStream &out, const Card *c);
QDataStream& operator >>(QDataStream &in, Card *c);
and
//QDataStream& operator <<(QDataStream &out, const Card *&c);
//QDataStream& operator >>(QDataStream &in, Card *&c);
If I use "Card *c", the data writes fine, but I get a SEGFAULT when I try to read. If I use "Card *&c", the program doesn't even recognize that I've overridden the operator, so it doesn't get called.
What am I doing wrong?
EDIT:
The problem comes when I am reading or writing "cards" which is a QHash defined in deck.h as
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;
}
...
Because the cards are stored as pointers in the QHash, I'm not sure how I am supposed to get around overriding the pointer operator. Is there a better way to read/write the QHash, or the *Card stored in the QHash?
EDIT:
As per Marek R's answer, I looked for a way to avoid writing a Card*. The solution was to iterate through the QHash and save each individual Card.
回答1:
First problem is that you are trying to do this operator for pointer. If my coworker would do this I would probably try to strangle him. For 99.9999% of cases never overload operators for pointers.
If you insist on doing that I guessing that you code with usage of this operator looks like this:
Card *uninitializedPointer;
someDataStream >> uninitializedPointer; // SEGFAULT
And this is wrong since uninitializedPointer
is .. its name says what is the problem, you are referring to restricted or random chunk of memory.
Probably you want (this is wrong to but it will work, I'm showing this only to explain crash not as a fix):
Card *initializedPointer = new Card;
someDataStream >> initializedPointer;
Or:
Card object;
someDataStream >> &object;
Do not try fix this by do allocation in operator or you will fry in hell :) Simply trash operators overloaded for pointers you really don't need them.
回答2:
The expected signatures for stream operators are:
stream& operator<<(stream& out, const T& t);
stream& operator>>(stream& in, T& t);
See How to properly overload the << operator for an ostream? or QDatastream operator>> for QList<Class*> for instance.
This applies to QDataStream as well. The difficulty here comes the fact that T
is a pointer type, but essentially you just replace T
by your pointer type. So your signatures should be :
QDataStream& operator<<(QDataStream &out, Card* const& c);
QDataStream& operator>>(QDataStream &in, Card*& c);
Note the placement of const
in Card* const
, because it is the pointer that needs to be const, not the pointee.
来源:https://stackoverflow.com/questions/23693425/qt-qdatastream-with-overloaded-operator-for-object-pointer-class