Я пытаюсь читать / писать свои собственные классы, используя 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, когда пытаюсь читать. Если я использую «Карту *&c «, программа даже не распознает, что я переопределил оператор, поэтому он не вызывается.
Что я делаю неправильно?
РЕДАКТИРОВАТЬ:
Проблема возникает, когда я читаю или пишу «карточки», которые представляют собой QHash, определенный в deck.h как
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 или * Card, хранящейся в QHash?
РЕДАКТИРОВАТЬ:
Согласно ответу Марека Р., я искал способ избежать написания Карты *. Решением было перебрать 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>> для QList<Учебный класс*> например.
Это относится и к QDataStream. Трудность здесь заключается в том, что T
это тип указателя, но по сути вы просто замените T
по вашему типу указателя. Так что ваши подписи должны быть:
QDataStream& operator<<(QDataStream &out, Card* const& c);
QDataStream& operator>>(QDataStream &in, Card*& c);
Обратите внимание на размещение const
в Card* const
потому что указатель должен быть константным, а не указателем.