【问题标题】:Serialize QVector of polymorphic pointers序列化多态指针的 QVector
【发布时间】:2014-11-23 15:39:25
【问题描述】:

我有一个AbstractIndex 定义其Items 的接口以及排序和查询算法。此外,我还有几个具体的索引,例如FileIndex 下面的示例。现在我想序列化 indizes。我猜serializeIndex() 有效,但我无法测试它。在FileIndex::buildIndex() 中,AbstractIndexProvider::Itemoperator>> 被调用。我试图向下转换_index,但出现奇怪的编译时错误。使用 boost 我可以轻松声明类型,但我想删除 boost 依赖项。 那么我该怎么做才能让 Qt 在 FileIndex::buildIndex() 中实例化正确的类?

class AbstractIndex
{
public:
    class Item;    
    void query(const QString &req, QVector<Item*> *res);

protected:
    virtual void buildIndex()      = 0;
    virtual void serializeIndex() const = 0;    
    QVector<Item*> _index;
};

class AbstractIndexProvider::Item
{
public:    
    QString _name;
    // Several pure virtual functions...

    // Serialization
    friend QDataStream &operator<<(QDataStream &out, AbstractIndexProvider::Item const * const item);
    friend QDataStream &operator>>(QDataStream &in, AbstractIndexProvider::Item *item);
};


/**************************************************************************/
class FileIndex : public AbstractIndexProvider
{
public:
    class Item;

protected:
    void buildIndex()           override;
    void serializeIndex() const override;
};

class FileIndex::Item : public AbstractIndexProvider::Item
{
    friend class FileIndex;

protected:
    QString _path;    
    friend QDataStream &operator<<(QDataStream &out, const FileIndex::Item &item);
    friend QDataStream &operator>>(QDataStream &in, FileIndex::Item &item);
};


/**************************************************************************/
void FileIndex::serializeIndex() const
{
    QFile file(_indexFile);
    if (file.open(QIODevice::ReadWrite| QIODevice::Text))
    {
        QDataStream stream( &file );
        stream << _index;
        return;
    }
}


/**************************************************************************/
void FileIndex::buildIndex()
{
    QFile file(_indexFile);
    if (file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        QDataStream stream( &file );
        stream >> _index;  // WHAT TO DO HERE?
        return;
    }
}

【问题讨论】:

    标签: c++ qt inheritance serialization polymorphism


    【解决方案1】:
    stream >> _index;  // WHAT TO DO HERE?
    

    QVector&lt;Item*&gt; _index;QVector,没有直接的二进制流方式。

    QDebug 有一种写QVector 的方法。如果您想要一种快速简便地进出文件系统或数据流的方法,QByteArray 处理得非常好。

    否则,如果您想坚持使用 QVector,请使用 foreach 或标准 for 循环或 java 样式迭代器或标准 lib 样式迭代器对其进行迭代。

    您的代码可能类似于:

    QDataStream stream( &file );
    for(int i = 0; i< _index.size(); i++)
    {
        stream << _index.at(i) << ",";
    }
    stream << "\n";
    return;
    

    http://qt-project.org/doc/qt-5/qlist.html#details

    http://qt-project.org/doc/qt-5/containers.html

    可以在以下位置找到 Qt 中一些更复杂的继承示例:模型/视图编程和 Qt 的图形视图框架。

    http://qt-project.org/doc/qt-5/graphicsview.html

    http://qt-project.org/doc/qt-5/model-view-programming.html

    http://qt-project.org/doc/qt-5/qabstractitemmodel.html

    http://qt-project.org/doc/qt-5/qmodelindex.html

    您是否还研究过 QFileInfo 类以及 Qt 文件系统查询中内置的过滤器和排序选项?

    http://qt-project.org/doc/qt-5/qdiriterator.html

    http://qt-project.org/doc/qt-5/qdir.html#entryInfoList

    QFileInfoList QDir::entryInfoList(const QStringList & nameFilters, Filters filters = NoFilter, SortFlags sort = NoSort) const
    

    希望对您有所帮助。

    【讨论】:

      【解决方案2】:

      您想要实现的是虚拟化对象的创建。在 Qt 中没有开箱即用的解决方案。所以,如果你不想使用 boost,你应该自己实现它。

      一种方法是为每个派生类添加一个类型标识符,并在某个工厂中注册类型-类对。当您序列化您的对象时,您还应该序列化它们的类型 ID。反序列化时,首先从数据流中读取类型 ID,然后使用对象工厂创建对象。

      这里有一些有用的链接:

      http://www.parashift.com/c++-faq/serialize-inherit-no-ptrs.html

      http://www.parashift.com/c++-faq/virtual-ctors.html

      Best Practice For List of Polymorphic Objects in C++

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-07
        • 1970-01-01
        相关资源
        最近更新 更多