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

锡安345

我有四个类(ABCD)经典的金刚石图案和下面的Container含有类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(...)
    }
}

所有类都具有谷物saveload功能,但是我仅在B和中包含它们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);

我得到以下输出:

Saving Container
Obj Addr: 0x23d2128 
Obj: 0x23d2130 0x23d2134 0x23d2138 // Fields adresses (f1,f2,f3)
Obj:  8 8 128 // Fields values
Saving Obj: 0x23d2128 // Same object
This: 0x23d2118 0x23d211c 0x23d2120 // Different field adresses !
This: 4293296 0 37569440 // Garbage

我的问题是:这很可能是谷物中的错误,还是我无法通过虚拟继承获得某些东西?

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

金丹

我无法在谷物的当前开发分支上重现您的错误,但是可以在当前的母版(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发布。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如果对象具有多态性而不是多重继承,则虚拟指针在对象中的位置是否不同?

来自分类Dev

如果对象具有多态性而不是多重继承,则虚拟指针在对象中的位置是否不同?

来自分类Dev

封装,抽象和多态性是否需要继承?

来自分类Dev

谷物序列化和多态性

来自分类Dev

失去继承和多态性

来自分类Dev

C ++多态性,重载和继承

来自分类Dev

Java中的继承和多态性

来自分类Dev

C#多态性和方法继承

来自分类Dev

Avro模式中的多态性和继承

来自分类Dev

Java解决父类和子类对象的多态性

来自分类Dev

多态性和参数?

来自分类Dev

多态性和参数?

来自分类Dev

ADT 和多态性

来自分类Dev

Matlab中的继承多态性

来自分类Dev

jQuery UI继承多态性

来自分类Dev

组成与继承,多态性呢?

来自分类Dev

多态性继承的类属性

来自分类Dev

jQuery UI继承多态性

来自分类Dev

继承中的 Java Upcasting 或多态性

来自分类Dev

如何使用继承/多态性将JSON字符串解析为C#对象?

来自分类Dev

在概念明确之前,多态性和继承的C习语是什么?

来自分类Dev

在这种情况下,继承和多态性如何工作?

来自分类Dev

多态性和继承在Java中抽象类的静态方法

来自分类Dev

在概念明确之前,多态性和继承的C习语是什么?

来自分类Dev

OCaml对象的多态性键入问题

来自分类Dev

数组中对象的C ++多态性

来自分类Dev

多态性对象的字符串

来自分类Dev

C ++多态性和虚函数

来自分类Dev

多态性和接口-澄清吗?