【问题标题】:Error C2679 while trying to serialize QList of custom class with QDatastream尝试使用 QDatastream 序列化自定义类的 QList 时出现错误 C2679
【发布时间】:2014-04-10 06:13:05
【问题描述】:

我有一个自定义类Foo

class Foo
{
public:
    // getters and setters
    // ...
private:
    QString string;
    QStringList list;
    int number;
}

Foo 的序列化已按预期工作:

QDataStream &operator<<(QDataStream &stream, const Foo &foo)
{
    stream<<foo.getString()<<foo.getList()<<foo.getNumber();
    return stream;
}

但是当我尝试序列化QList&lt;Foo&gt; 时,我得到了

error C2679: binary '<<' : no operator found which takes a right-hand operand of type “const Foo”

指向对应的Qt代码(qdatastream.h):

template <typename T>
QDataStream& operator<<(QDataStream& s, const QList<T>& l)
{
    s << quint32(l.size());
    for (int i = 0; i < l.size(); ++i)
        s << l.at(i); // <--- compiler error here
    return s;
}

我知道QList&lt;T&gt;::at() 返回const T &amp;,但我不知道为什么它会在这里编译失败。请指出我的错误,我想知道如何解决这个问题。另外,如果我错过了代码的必要部分,请告诉我。谢谢!

[编辑]: 作为参考,我的环境是带有 MSVC2010/Win 7 的 Qt 4.8.5,我正在使用 Qt creator。

另外,这就是我序列化QList&lt;Foo&gt;的方式:

QFile file("file.dat");
file.open(QIODevice::ReadWrite);
QDataStream out(&file);
out.setVersion(QDataStream::Qt_4_8);

out<<fooList; // It's the instant of QList<Foo> and it's not a pointer
//^^^^^^^^^^ compiler errors occurs as this line is added

[上次编辑]:

我终于搞清楚是怎么回事了:

我定义的用于序列化Foo 的运算符重载写在一个单独 .cpp 文件中,其中

QDataStream &operator<<(QDataStream &stream, const Foo &foo)
{
    stream<<foo.getString()<<foo.getList()<<foo.getNumber();
    return stream;
}

foo.cpp里面。

上面的代码可以编译,但现在我意识到它永远不会被使用!

QList&lt;Foo&gt; 的序列化在另一个文件notFoo.cpp 中实现,这是一个“更大的类”

当我编译notFoo.cpp时,只能找到标题qdatastream.h中的定义和方法,因此出现error C2679,其中:

template <typename T>
QDataStream& operator<<(QDataStream& s, const QList<T>& l)
{
    s << quint32(l.size());
    for (int i = 0; i < l.size(); ++i)
        s << l.at(i); // <--- compiler error here
    return s;
}

这表明编译器不知道如何进一步序列化类型Foo

binary '<<' : no operator found which takes a right-hand operand of type “const Foo”

这意味着找不到s &lt;&lt; l.at(i);&lt;&lt;(因为我在另一个.cpp 文件中定义了它)

我把序列化方法从Foo.cpp移到notFoo.cpp之后,代码终于可以编译了。

[结论]:

编译器没有在Foo.h 中找到函数签名,因为我在Foo.cpp 中内联定义了流运算符。

【问题讨论】:

  • 嗯,奇怪,但这段代码对我有用(Win7、Qt 4.8.5、MSVC9)。
  • 这很奇怪。我已向 OP 添加了更多信息。
  • 什么是fooList 以及如何创建和填充它?
  • QList&lt;Foo&gt; fooList; 之后,fooList.append(Foo); 我的应用在运行时将Foo 附加到QList
  • @vahancho 我不确定是否有此信息。帮助:我将fooList 保存在一个对象中。但是我经常遇到这个错误,要么我调用 getter 以返回 fooList 以输出数据流,要么将 fooList 移动到 public 并直接调用它。

标签: c++ qt serialization


【解决方案1】:

您需要在声明序列化类型的同一标头中声明流运算符:

// Foo.h
#include <QString>
#include <QDataStream>

class Foo
{
public:
    // getters and setters
    // ...
private:
    QString string;
    QStringList list;
    int number;
};

QDataStream &operator<<(QDataStream &stream, const Foo &foo);

通常,操作符的实现将在您实现Foo的文件中,但它可以在任何.cpp文件中,真的:

// Foo.cpp

Foo::Foo() {
  ...
}

...

QDataStream &operator<<(QDataStream &stream, const Foo &foo)
{
    stream<<foo.getString()<<foo.getList()<<foo.getNumber();
    return stream;
}

【讨论】:

  • 感谢您的回答,我不应该这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-26
  • 2010-11-29
  • 2017-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多