我有一个自定义课程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
内定义了内联的流操作符。
答案 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;
}