虚拟继承和多态:谷物库是否与对象布局混乱?

时间:2016-02-13 01:40:32

标签: c++ inheritance polymorphism cereal

我有四个类(ABCD)遵循经典菱形图案和Container类包含{{1 }}。我想使用cereal序列化库序列化这些类。

unique_ptr<A>

所有课程都有谷物struct A {int f1; int f2; int f3} struct B : public virtual A { template<typename Archive> inline void save(Archive& ar) const { std::cerr << "Saving Obj: " << this << std::endl; std::cerr << "This: " << &(this->f1) << " " << &(this->f2) << " " << &(this->f3) << std::endl; std::cerr << "This: " << this->f1 << " " << this->f2 << " " << this->f3 << std::endl; }; } }; struct C : public virtual A {}; struct D : public B, public C {}; #include <cereal/archives/binary.hpp> CEREAL_REGISTER_TYPE(B); CEREAL_REGISTER_TYPE(C); CEREAL_REGISTER_TYPE(D); struct Container { std::unique_ptr<A> obj; template<typename Archive> inline void save(Archive& ar) const { std::cerr << "Saving Container" << std::endl; std::cerr << "Obj Addr: " << obj.get() << std::endl; std::cerr << "Obj: " << &(obj->f1) << " " << &(obj->f2) << " " << &(pq->f3) << std::endl; std::cerr << "Obj: " << " " << pq->sq_count << " " << pq->sq_bits << " " << pq->dim << std::endl; ar(obj); // Call serialization for obj, ie B.save(...) } } save个功能,但我只将它们包含在loadB中,因为它们是本例中唯一使用的。< / p>

我按如下方式使用这些类:

Container

我得到以下输出:

std::unique_ptr<A> obj(new B);
obj->f1 = 8;
obj->f2 = 8;
obj->f3 = 128;
std::unique_ptr<Container> db(new Container);
db.obj = std::move(obj);

std::ofstream out_file(out_filename);
cereal::BinaryOutputArchive out_archive(out_file);
out_archive(db);

我的问题是:这可能是谷物中的一个错误,还是我的虚拟继承没有?

是否期望给定对象的字段地址在C ++程序中发生变化?

1 个答案:

答案 0 :(得分:1)

我不能在当前的谷物开发分支上重现你的错误,但是我可以在当前的master(1.1.2)上重现它。我修改了你的代码以实际编译:

#include <cereal/types/memory.hpp>
#include <cereal/types/polymorphic.hpp>
#include <cereal/archives/json.hpp>
#include <fstream>
#include <iostream>

struct A {
  int f1; int f2; int f3;
  virtual ~A() {}

  template<typename Archive>
    void serialize( Archive & ar )
    {
      std::cerr << "Saving A Obj: " << this << std::endl;
      std::cerr << "This: " << &(this->f1) << " "
        << &(this->f2) << " " << &(this->f3) << std::endl;
      std::cerr << "This: " << this->f1 << " "
        << this->f2 << " " << this->f3 << std::endl;
    };
};

struct B : public virtual A {
  template <class Archive>
  void serialize( Archive & ar )
  {
    std::cerr << "Saving B Obj: " << this << std::endl;
    std::cerr << "This: " << &(this->f1) << " "
      << &(this->f2) << " " << &(this->f3) << std::endl;
    std::cerr << "This: " << this->f1 << " "
      << this->f2 << " " << this->f3 << std::endl;

    ar( cereal::virtual_base_class<A>( this ) );
  }

  virtual ~B() {}
};

CEREAL_REGISTER_TYPE(B);

struct Container {
    std::unique_ptr<A> obj;

    template<typename Archive>
      void serialize( Archive & ar )
    {
        std::cerr << "Saving Container (A)" << std::endl;
        std::cerr << "Obj Addr: " << obj.get() << std::endl;
        std::cerr << "Obj: " << &(obj->f1) << " " << &(obj->f2)
            << " " << &(obj->f3) << std::endl;

        ar(obj); // Call serialization for obj, ie B.save(...)
    }
};

int main()
{
  std::unique_ptr<A> ptr(new B());
  ptr->f1 = 8;
  ptr->f2 = 8;
  ptr->f3 = 128;
  std::unique_ptr<Container> db(new Container());
  db->obj = std::move(ptr);

  std::stringstream ss;
  {
    cereal::JSONOutputArchive out_archive(ss);
    out_archive(db);
  }

  std::cout << ss.str() << std::endl;
}

1.1.2的输出:

Saving Container (A)
Obj Addr: 0x1738d78
Obj: 0x1738d80 0x1738d84 0x1738d88
Saving B Obj: 0x1738d78
This: 0x1738d78 0x1738d7c 0x1738d80
This: 4316664 0 8
Saving A Obj: 0x1738d70
This: 0x1738d78 0x1738d7c 0x1738d80
This: 4316664 0 8
{
    "value0": {
        "ptr_wrapper": {
            "valid": 1,
            "data": {
                "value0": {
                    "polymorphic_id": 2147483649,
                    "polymorphic_name": "B",
                    "ptr_wrapper": {
                        "valid": 1,
                        "data": {
                            "value0": {}
                        }
                    }
                }
            }
        }
    }
}

使用develop的输出:

Saving Container (A)
Obj Addr: 0x1f74e18
Obj: 0x1f74e20 0x1f74e24 0x1f74e28
Saving B Obj: 0x1f74e10
This: 0x1f74e20 0x1f74e24 0x1f74e28
This: 8 8 128
Saving A Obj: 0x1f74e18
This: 0x1f74e20 0x1f74e24 0x1f74e28
This: 8 8 128
{
    "value0": {
        "ptr_wrapper": {
            "valid": 1,
            "data": {
                "value0": {
                    "polymorphic_id": 2147483649,
                    "polymorphic_name": "B",
                    "ptr_wrapper": {
                        "valid": 1,
                        "data": {
                            "value0": {}
                        }
                    }
                }
            }
        }
    }
}

所以导致这个问题的任何原因都可能在目前的谷物开发部门得到修复,谷物将在不久的将来以1.2的形式发布。