尝试使用QDatastream序列化自定义类的QList时出错C2679

时间:2014-04-10 06:13:05

标签: c++ qt serialization

我有一个自定义课程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<Foo>时,我得到了

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<T>::at()会返回const T &,但我不知道为什么它不能在这里编译。请指出我的错误,我想知道如何解决这个问题。另外,如果我错过了必要的代码部分,请告诉我。谢谢!

[修改]: 作为参考,我的环境是Qt 4.8.5,MSVC2010 / Win 7,我正在使用Qt创建者。

此外,这是我序列化QList<Foo>

的方式
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<Foo>的序列化在另一个文件notFoo.cpp中实现,该文件是&#34;更大的类&#34;

在编译notFoo.cpp时,只能找到标题qdatastream.h中的定义和方法,因此错误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”

表示找不到<<的{​​{1}}(因为我在另一个s << l.at(i);文件中定义了它)

将序列化方法从.cpp移动到Foo.cpp后,最终可以编译代码。

[结论]:

编译器在notFoo.cpp中找不到函数签名,因为我在Foo.h内定义了内联的流操作符。

1 个答案:

答案 0 :(得分: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;
}