对象是不是以序列化形式有效? c++/继承/序列化

Posted

技术标签:

【中文标题】对象是不是以序列化形式有效? c++/继承/序列化【英文标题】:Is an object valid in serialized form? c++/inheritance/serialization对象是否以序列化形式有效? c++/继承/序列化 【发布时间】:2016-11-07 15:09:02 【问题描述】:

我问这个是因为即使它似乎有效,但我觉得它不应该。目标是让一组对象保持活动状态,并对其进行一般访问。这就是我目前所拥有的:

获取基指针访问:

struct base  virtual void tick() = 0; ; //ptr access

从它继承的不同类型:

struct :public base

    void tick()  cout << "im type 1" << endl; 
type1;

struct :public base

    void tick()  cout << "im type 2" << endl; 
type2;

然后是一个容器类,它应该能够存储任意数量的这些序列化:

class control

    struct xtype //struct for organizing objects
    
        vector<char>charbuf; //serialized object
    xtype_template;

    vector<xtype>xtype_vec;

public:

    template<typename T> base* tell_to(T &input) //take object, return (base*)
     
        xtype_template.charbuf.resize(sizeof(input));
        memcpy(xtype_template.charbuf.data(), (char*)&input, sizeof(input));

        xtype_vec.push_back(xtype_template);  //push back with template after filling

        return (base*)xtype_vec[xtype_vec.size() - 1].charbuf.data(); //pointer to data
      
xcontainer; //container object

然后调用:

auto ptr = controller.tell_to(type1); //becomes base* 
auto ptr2 = controller.tell_to(type2);

您可以通过以下方式访问任一静态大小的序列化对象及其状态:

ptr->tick(); //which will output "im type 1" to console
ptr2->tick() //"im type 2"

但这合法吗?这些序列化版本有实际类型吗?直接使用基指针访问序列化对象是非法还是错误?


最接近的可能答案:由于is_trivially_copyable 上的返回显示为 false,因此在获得基础继承后对象可能无法安全管理。

跟进:这种方法似乎有效,并且摆弄is_trivially_copyable,似乎表明使对象继承方法会使其不安全。然而,基本方法并没有使其不安全,这让我想知道安全性是否仅适用于系统之间的导出、保存到文件或通过网络传输。也许检查只是假设虚拟参考使它们不安全?

跟进 2:如果字符仍然在内存中的同一位置,那么它们的访问方式是否重要?我敢打赌,这种方法唯一真正的问题是存储的对象是否具有在存储后会改变其大小的元素。

【问题讨论】:

我想在一个向量(向量)中有一个不同对象的集合。这个想法是存储告诉容器 tick() 应该做什么的函数对象,或者在有意义的情况下泛化对跨类型方法的访问 像向量>objs_owner; ?嗯,我认为我不熟悉这种方法。它不会对物体进行切片? 看我的回答,我原来的评论是错误的。 我不相信这种方法对于我使用它的目的是不安全的。 【参考方案1】:

你的行为是非法的。当对象为TriviallyCopyable 时,您只能将memcpy 对象作为chars 的数组。而你的对象不是,因为它有虚函数。

您应该简单地存储一个指向新分配对象的(唯一)指针,而不是这样做,并避免任何强制转换来强制层次结构。像这样:

class xtype

    std::unique_ptr<base> ptr;

public:

    template<typename T> base* serial_acc(T &input) //take object, return (base*)
     
        static_assert(std::is_base_of<base, T>::value, "Please use proper type");
        ptr = std::make_unique<base>(input);
        return ptr;
      
 xcontainer;

【讨论】:

另外,除了TriviallyCopyable,如果chars 与类型正确对齐,您只能将chars 转换回指向对象的指针(否则您必须将它们复制回对齐的存储)。 @AndréSassi,虽然通常是正确的,但对齐是实现定义的,主要平台上的主要实现支持非对齐访问。 我仍然不相信这对于我正在尝试做的事情是不安全的。联网和导出到文件可能不安全,但私下这样? @SergeyA @Charlie,是的,这是不安全且完全奇怪的。你仍然没有解释为什么你需要这个。 我正在尝试完成一些不同的事情。这只是其中的一部分,能够将不同的对象存储在 1 个容器中,然后循环通过它们的方法,就好像它们是一样的。理想情况下,我可以这样做:vectorany_method_queue;并将任何方法指针传递给它【参考方案2】:

用户Andy Prowl给出的工作示例

#include <vector>
#include <memory>
#include <iostream>
using namespace std;

struct base 

    virtual void tick() = 0; 
;

struct type1 : base

    virtual void tick() override  cout << "im type 1"<<endl; 
;

struct type2 : base

    virtual void tick() override  cout << "im type 2" << endl; 
;

struct controller

    vector<unique_ptr<base>> objects; 

    void cycle_tick() for (auto const& ptr : objects)ptr->tick();

    void add_object(unique_ptr<base> obj) objects.emplace_back(move(obj));

;

int main()

    auto t1 = unique_ptr<type1>(new type1);
    auto t2 = unique_ptr<type2>(new type2);

    controller ctrl_object;
    c.add_object(move(t1));
    c.add_object(move(t2));

    ctrl_object.cycle();

【讨论】:

以上是关于对象是不是以序列化形式有效? c++/继承/序列化的主要内容,如果未能解决你的问题,请参考以下文章

什么是序列化

0

使用C#以二进制序列化字符串,并使用C ++对其进行反序列化

0802 DRF 视图

java 实现序列化的两种方式

TypeError('不是一个有效的非字符串序列或映射对象',)