【问题标题】:Implementing MFC Serialazation for base and derived classes为基类和派生类实现 MFC 序列化
【发布时间】:2020-01-30 16:59:07
【问题描述】:

我有两个类:Product 和派生 Juice。我需要为这些类实现 MFC Serialazation。

class Product : CObject
{
protected:
    DECLARE_SERIAL(Product) //IMPLEMENT_SERIAL(Product, CObject, 0) in .cpp

    CString name;
    int expiring;
    double price;
public:
    Product();
    ~Product();

    virtual void input_data();
    virtual void print_data();

    virtual void Serialize(CArchive& archive)
    {
        CObject::Serialize(archive);

        if (archive.IsStoring())
            archive << name << expiring << price;
        else
            archive >> name >> expiring >> price;
    };

};
class Juice :
    public Product
{

private:
    double volume; 
    CString taste;
public:
    Juice();
    ~Juice();

    void input_data() override;
    void print_data() override;

    void Serialize(CArchive& archive) override
    {
        Product::Serialize(archive);
        if (archive.IsStoring())
            archive << volume << taste;
        else
            archive >> volume >> taste;
    }

};

为了存储类的对象,我有 Stock 类,它有 Product 类指针的容器。

class Stock
{
private:
    vector<shared_ptr<Product>> stock;
public:
    Stock();
    ~Stock();

    void Add(shared_ptr<Product> p); 
    void Print(); 

    bool Save(string fname);
    bool Load(string fname);

    void Clear();
};

在保存和加载方法中,我正在尝试实现序列化(根据本主题 C++ MFC Serialization 中的讨论)。

bool Stock::Save(string fname)
{
    CFile out;
    if (!out.Open(fname.c_str(), CFile::modeWrite | CFile::modeCreate))
        return false;

    CArchive ar(&out, CArchive::store);
    ar.WriteCount(stock.size());
    for (auto it = stock.begin(); it != stock.end(); ++it)
    {
        (*it)->Serialize(ar);
    }
    ar.Close();
    out.Close();
    return true;
}

bool Stock::Load(string fname)
{
    CFile in;
    if (!in.Open(fname.c_str(), CFile::modeRead))
        return false;

    CArchive ar(&in, CArchive::load);
    int cnt = ar.ReadCount();
    for (int i = 0; i < cnt; i++)
    {
        auto p = make_shared<Product>();
        p->Serialize(ar);
        stock.push_back(p);
    }
    ar.Close();
    in.Close();
    return true;
}

现在我遇到了问题。

从文件中读取对象时,Juice 对象的读取方式与 Product 类似(没有 volumetaste 字段)。 Juice 之后对象的读取是从 Juice 的其余信息开始的,所以我在 Product 的 Serialaize 方法中得到了 CArchiveException

如果我只使用 Product 对象添加到 Stock 中,一切正常。我的错误是什么,我应该怎么做才能正确实现 MFC 序列化?

【问题讨论】:

  • 你的 Juice 类中需要一个 DECLARE_SERIAL。
  • 是的。我为 Product 进行了公共继承,并为 Juice 类添加了 DECLARE_SERIAL(Juice) 和 IMPLEMENT_SERIAL(Juice, CObject, 0)。但还是有同样的问题
  • Juice = Product,而不是 CObject 的基类
  • 我应该使用 IMPLEMENT_SERIAL(Juice, Product, 0) 吗?我做到了,但仍然遇到同样的问题。如果我不将 Juice 对象添加到 Stock 对象,一切正常
  • 只是为了调查,将Stock 类的stock 成员“临时”更改为原始指针我>?只是想:也许这是 STL 和 MFC 的 DECLARE_SERIAL 多态的奇怪实现之间的错误/冲突?

标签: c++ inheritance serialization mfc carchive


【解决方案1】:

Stock::Save 需要更改为:

for (auto it = stock.begin(); it != stock.end(); ++it)
{
    ar << (*it).get();
}

Stock::Load 需要改为:

for (int i = 0; i < cnt; i++)
{
    Product* obj = nullptr;
    ar >> obj;

    stock.emplace_back(obj);
}

当您使用 ar

作为参考,下面是 MFC 序列化代码在 CObArray 内部的样子(如果你只坚持使用 MFC,基本上你会使用它而不是向量)

if (ar.IsStoring())
{
    ar.WriteCount(m_nSize);
    for (INT_PTR i = 0; i < m_nSize; i++)
        ar << m_pData[i];
}
else
{
    DWORD_PTR nOldSize = ar.ReadCount();
    SetSize(nOldSize);
    for (INT_PTR i = 0; i < m_nSize; i++)
        ar >> m_pData[i];
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多