Qt — QDataStream с перегруженным оператором & lt; & lt; для указателя объекта (Class *)

Я пытаюсь читать / писать свои собственные классы, используя 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 и сохранить каждую отдельную карту.

1

Решение

Первая проблема заключается в том, что вы пытаетесь сделать этот оператор для указателя.
Если бы мой коллега сделал это, я, вероятно, попытался бы его задушить. В 99,9999% случаев никогда не перегружайте операторы указателями.

Если вы настаиваете на этом, я предполагаю, что ваш код с использованием этого оператора выглядит так:

Card *uninitializedPointer;
someDataStream >> uninitializedPointer; // SEGFAULT

И это неправильно, так как uninitializedPointer это … его имя говорит о том, в чем проблема, вы имеете в виду ограниченный или случайный кусок памяти.
Вероятно, вы хотите (это неправильно, но это будет работать, я показываю это только для объяснения сбоя, а не исправления):

Card *initializedPointer = new Card;
someDataStream >> initializedPointer;

Или же:

Card object;
someDataStream >> &object;

Не пытайтесь исправить это, сделав выделение в операторе, иначе вас пожрут в аду 🙂
Просто операторы мусора перегружены для указателей, они вам действительно не нужны.

4

Другие решения

Ожидаемые подписи для потоковых операторов:

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потому что указатель должен быть константным, а не указателем.

1

По вопросам рекламы [email protected]