C++ 在C++;?

C++ 在C++;?,c++,deserialization,binary-deserialization,C++,Deserialization,Binary Deserialization,我试图实现反序列化,其中到字段/成员的映射只在运行时才知道(这很复杂)。不管怎样,我想做的是如下所示: Class A { public: int a; // index 0 float b; // index 1 char c; // index 2 } 然后我有两个数组,一个带有字段索引,另一个带有指示类型的内容。然后我想迭代数组并从字节流写入字段 很抱歉,我的描述很糟糕,但我不知道如何在代码中实现它。任何想法都将不胜感激,谢谢 让编译器来做: 编

我试图实现反序列化,其中到字段/成员的映射只在运行时才知道(这很复杂)。不管怎样,我想做的是如下所示:

Class A
{
  public:
    int a;    // index 0
    float b;  // index 1
    char c;   // index 2
} 
然后我有两个数组,一个带有字段索引,另一个带有指示类型的内容。然后我想迭代数组并从字节流写入字段


很抱歉,我的描述很糟糕,但我不知道如何在代码中实现它。任何想法都将不胜感激,谢谢

让编译器来做:


编写一个
操作符>>
函数。

有许多问题和决策需要解决。在最简单的情况下,您可以将偏移量保留在每个字段的
A
,您可以打开类型并通过指向该字段的指针进行设置。例如-假设在输入流中有一个
int16\u t
编码字段号,不努力使用
static\u cast
等。这样做稍微好一点,假设字段号输入终止符为0

A a;
char* pa = (char*)&a;
char* p_v = (char*)&input_buffer;

...
while ((field_num = *(int16_t)p_v) && (p_v += sizeof(int16_t)))
    switch (type[field_num])
    {
      case Int32:
        *(int32_t*)(p_a + offset[field_num]) = *(int32_t*)(p_v);
        p_v += sizeof(int32_t);
        break;
      ...
    }

您可能想考虑使用“代码> NtoHLL())/代码>等来处理SudiaNess转换。

< P>我想不出一个语言结构,它可以在运行时给出一个字段索引。如果可以让“type”数组实际包含字段大小,则可以执行以下操作:

istream &in = <get it somehow>;
size_t *field_size = <get it somehow>;
size_t num_of_fields = <get it somehow>;
A a;

char *ptr = reinterpret_cast<char *>(&a);
for (int i = 0; i < num_of_fields; i++)
{
    in.read(ptr, field_size[i]);
    ptr += field_size[i];
}
istream&in=;
大小*字段大小=;
size_t num_of_字段=;
A A;
char*ptr=重新解释演员表(&a);
for(int i=0;i
请注意,如果您的类很简单并且没有任何虚拟函数成员,那么这将是正确的 (或从这样的类继承)。如果是这种情况,最好包含一个虚拟成员 获取类中字段开始的字节偏移量:

class A
{
    int __dummy;   /* must be the first data member in the class */

    ...
    <rest of your class definition here>
};
A类
{
int _dummy;/*必须是类中的第一个数据成员*/
...
};
现在更改ptr的初始化,如下所示:

ptr = reinterpret_cast<char *>(&a) + offsetof(A, __dummy);
ptr=reinterpret\u cast(&a)+偏移量(a,\u dummy);

此代码的另一个隐式假设是,运行此代码的机器和接收序列化数据的机器的字节顺序相同。如果不是,则需要转换从流中读取的数据的字节顺序。此转换当然取决于类型,但每个字段可以有另一个转换函数数组。

是的,您可以,但在进行转换时需要注意两件事

首先,请确保从
(const char*)&A.A
开始编写,因为所有编译器都会在对象的开头附加与您无关的内容(例如,visualc将vtable放在那里),如果从对象的地址开始编写,则不会编写您认为自己是的内容

其次,在声明任何需要写入磁盘的类之前,您可能需要执行一个
#pragma pack(1)
,因为编译器通常会对齐类成员以提高DMA传输的效率,并且最终可能会遇到问题


在动态方面,如果可以为每个字段组合定义一个类,那么可以这样做,否则,最好在类中包含一个哈希表,并通过将键值对写入文件来序列化/反序列化其内容

我正在考虑使用另一个指向字段的空指针数组并执行memcpy。不保存类型,只保存字段的长度(字节)。不确定是否最好的办法是避免牺牲McCPy——这是一个危险的函数,如果你写了一个字节,你就可以很容易地让整个OS死掉,因为编程错误使用<代码> MycPy < /C>几乎是C++中的一个好主意,除了基本类型,比如“代码> int <代码>,<代码> char < /C>
float
和类似的。就这样?这就是完整的答案?如果错误代码。。。使用移位运算进行反序列化是。。。哑的抱歉,这只是我的经验。编译器会知道运行时的类型吗?这对我来说是个棘手的问题。如果我将指针放入和数组中,它们必须是空的*对吗?因为不支持多类型数组?你是建议使用operator>>函数而不是memcpy only或其他什么吗?Specializet:我有一个问题,字段映射只能在运行时给出。你有更好的解决方案吗?既然我成为了巨魔的牺牲品,你将被迫重新发明轮子并创建自己的序列化/反序列化-这在设计上很容易出错,而且会花费很多时间。我指出了正确的答案(即:使用图书馆),但不管怎样,我认为整个网站都充斥着巨魔,那些把观点当作事实传播的人,还有那些甚至不会说英语的人,因此我将离开。我怀疑这个网站是又一个巨魔池。。。我是对的。