对象是否以序列化形式有效? C ++ /继承/串行化

时间:2016-11-07 15:09:03

标签: c++ pointers inheritance

我问这个,因为即使它似乎工作,我觉得它不应该。目标是让一组对象保持活动,并对它们进行一般访问。这就是我现在所拥有的:

获取基本指针:

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:如果字符保留在内存中的相同位置,它们的访问方式是否重要?我敢打赌,这种方法唯一真正的问题是,如果存储的对象具有在存储后会改变其大小的元素。

2 个答案:

答案 0 :(得分:6)

你在做什么是非法的。当对象为memcpy时,您只能char一个对象作为TriviallyCopyable的数组。而且你的对象不是,因为它有虚函数。

您应该只是将(唯一的)指针存储到新分配的对象,而不是执行此操作,并避免任何强制转换来强制执行层次结构。像这样:

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;

答案 1 :(得分:0)

用户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();
}