Qt - 带有重载运算符的 QDataStream<<用于对象指针 (Class*)

Qt - QDataStream with overloaded operator<< for object pointer (Class*)

本文关键字:lt 指针 对象 Class 用于 运算符 重载 QDataStream Qt      更新时间:2023-10-16

我正在尝试使用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* constconst的位置,因为它是需要const的指针,而不是指针。