使用 QDataStream 序列化自定义类导致 C2679 错误

Posted

技术标签:

【中文标题】使用 QDataStream 序列化自定义类导致 C2679 错误【英文标题】:Using QDataStream to serialize custom class causes C2679 error 【发布时间】:2015-11-22 17:03:34 【问题描述】:

我正在编写一个应用程序,在该应用程序中我需要序列化以将一些数据存储在文件中。对于序列化,我想使用QDataStream 类。

由于此编译器错误,我无法编译我的代码:

错误 1 ​​错误 C2679: 二进制 '

请参阅下面的相关代码。有人知道这里发生了什么吗?

有一个similar question 对我没有帮助。当我按照那里描述的步骤操作时,我收到了这个(类似的)错误:

错误 1 ​​错误 C2678: 二进制 '


这是我的问题:

我要序列化的是一个叫CMPProject的类。

CMPProject 举行

CListModel* m_pData; QDateTime m_dateTimeCreated;

这基本上是应该序列化的。

CMPProject 有运营商将其内容流式传输到 QDataStream。

MPProject.h:

#ifndef _MPPROJECT_
#define _MPPROJECT_

#include <QtCore/QString>
#include <QtCore/QFile>
#include <QtCore/QDateTime>

#include "ListModel.h"

class CMPProject

public:
    // ...

    friend QDataStream& operator <<(QDataStream& stream, const CMPProject& project);
    friend QDataStream& operator >>(QDataStream& stream, CMPProject& project);

private:
    static const quint32 m_streamHeader = 0x1329453;
    QFile* m_pFile;
    CListModel* m_pData;
    QDateTime m_dateTimeCreated;
;

#endif // _MPPROJECT_

MPProject.cpp中的数据流操作符:

QDataStream& operator <<(QDataStream& stream, const CMPProject& project)

    return stream << project.m_dateTimeCreated << *(project.m_pData);


QDataStream& operator >>(QDataStream& stream, CMPProject& project)

    return stream >> project.m_dateTimeCreated >> *(project.m_pData);

m_pData 的类型为 CListModelCListModel 包含存储为QList&lt;CListItem&gt; 的实际数据。

为了序列化 CListModel,我在 ListModel.h 中添加了相应的运算符:

#ifndef _LISTMODEL_
#define _LISTMODEL_

#include <QtCore/QAbstractListModel>
#include <QtCore/QList>
#include <QtCore/QStringList>

#include "ListItem.h"

typedef QMap<unsigned int, QString> TValueMap;

class CListModel : public QAbstractListModel

public:
    // ...

    template<typename T>
    friend void operator <<(QVariant& data, const QList<T>& target);

    template<typename T>
    friend void operator >>(const QVariant& data, QList<T>& target);

    friend QDataStream& operator <<(QDataStream& stream, const CListModel& listModel);
    friend QDataStream& operator >>(QDataStream& stream, CListModel& listModel);

private:    

    QList<CListItem> m_items;
;

#endif // !_LISTMODEL_

ListModel.cpp

template<typename T>
void operator <<(QVariant& data, const QList<T>& target)

    QVariantList list;
    list.reserve(target.count());
    for (int i = 0; i < target.count(); i++) 
        QVariant item;
        item << target[i];
        list.append(item);
    
    data = list;


template<typename T>
void operator >>(const QVariant& data, QList<T>& target)

    QVariantList list = data.toList();
    target.reserve(list.count());
    for (int i = 0; i < list.count(); i++) 
        T item;
        list[i] >> item;
        target.append(item);
    


QDataStream& operator <<(QDataStream& stream, const CListModel& listModel)

    // ERROR C2679 does not occur when I change this line to "return stream;"
    return stream << listModel.m_items;


QDataStream& operator >>(QDataStream& stream, CListModel& listModel)

    return stream >> listModel.m_items;

为了序列化listModel.m_itemsCListItem 类型的对象)的内容,我在 ListItem.h 中实现了相应的运算符:

#ifndef _LISTITEM_
#define _LISTITEM_

#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QDateTime>
#include <QtCore/QVariantMap>

class CListItem

public:
    // ...

    friend void operator <<(QVariant& data, const CListItem& target);
    friend void operator >>(const QVariant& data, CListItem& target);
private:
    QString m_name;
    QString m_domain;
    QString m_login;
    QString m_password;
    QDateTime m_LastModified;
;

#endif // !_LISTITEM_

ListItem.cpp

template<typename T>
void operator <<(QVariant& data, const T& target)

    data = QVariant::fromValue<T>(target);


template<typename T>
void operator >>(const QVariant& data, T& target)

    target = data.value<T>();


void operator <<(QVariant& data, const CListItem& target)

    QVariantMap map;
    map["name"] << target.m_name;
    map["domain"] << target.m_domain;
    map["login"] << target.m_login;
    map["password"] << target.m_password;
    map["dateModified"] << target.m_LastModified;
    data << map;


void operator >>(const QVariant& data, CListItem& target)

    QVariantMap map;
    data >> map;
    map["name"] >> target.m_name;
    map["domain"] >> target.m_domain;
    map["login"] >> target.m_login;
    map["password"] >> target.m_password;
    map["dateModified"] >> target.m_LastModified;

【问题讨论】:

您是否能够确定是哪一行代码导致了这种情况? @LogicStuff 我编辑了我的问题以突出显示该行。它在 ListModel.cpp 中。 【参考方案1】:

我修好了。

问题是我没有操作员将我的 QList 放入 QDataStream。但是我定义了包装器来将我的列表存储在 QVariant 中,所以(当然)我应该使用它们。

QDataStream& operator <<(QDataStream& stream, const CListModel& listModel)

    QVariant var;
    var << listModel.m_items;
    return stream << var;


QDataStream& operator >>(QDataStream& stream, CListModel& listModel)

    QVariant var;
    stream >> var;

    var >> listModel.m_items;

    return stream;

【讨论】:

【参考方案2】:

看起来这里没有为参数重载operator&lt;&lt;QDataStream &amp;QList&lt;CListItem&gt; const&amp;。在参考文献here 和here 中,没有任何记录。

第二个错误解决了这个问题,但也应该提到QList&lt;CListItem&gt; 参数。这是完整的错误信息吗?

基本上,你应该使用这个:

QDataStream& operator <<(QDataStream& stream, const CListModel& listModel)

    for(auto const& item : listModel.m_items)
        stream << item; // write elements one by one

    return stream;

此模板可能为您提供多种类型(或类似于Pretty-print C++ STL containers):

template <typename Stream, typename Containter>
Stream& operator <<(Stream& stream, const Containter& container)

    for(auto const& item : container)
        stream << item;

    return stream;

您的代码将有效,无需更改您定义的operator&lt;&lt;。希望对您有所帮助。

【讨论】:

以上是关于使用 QDataStream 序列化自定义类导致 C2679 错误的主要内容,如果未能解决你的问题,请参考以下文章

Qt 自定义序列化

(反)序列化 QSet 与枚举使用 QDataStream

使用带有 QDataStream 的自定义 QMetaType

Mongo自定义序列化程序导致无法创建抽象类

Qt QSharedMemory 和 QDataStream

Qt学习之QDataStream