【发布时间】:2018-01-13 18:52:04
【问题描述】:
编辑:我意识到下面的代码是一个很好的例子,说明你不能在 C++ 中使用任何不是 POD 的东西。
似乎没有办法摆脱在类中的 typeid 并在接收方进行某种切换或表查找(两者都必须小心维护)以重建对象。
我已经编写了一些玩具代码来序列化对象和两个独立的主代码来将它们写入/读取文件。
common.h:
#include <iostream>
using namespace std;
template <typename T>
size_t serialize(std::ostream & o, const T & t) {
const char * bytes = reinterpret_cast<const char*>(&t);
for (size_t i = 0; i < t.size(); ++i) {
o << bytes[i];
}
return t.size();
}
size_t deserialize(std::istream & i, char * buffer) {
size_t len = 0;
char c;
while (i.get(c)) {
buffer[len] = c;
++len;
}
return len;
}
// toy classes
struct A {
int a[4];
virtual ~A() {}
virtual void print(){cout << "A\n";}
virtual size_t size() const {return sizeof(*this);}
};
struct B: A {
int b[16];
virtual ~B() {}
virtual void print(){cout << "B\n";}
virtual size_t size() const {return sizeof(*this);}
};
out.cpp:
#include <fstream>
#include "common.h"
int main() {
B b;
A& a = *static_cast<A*>(&b);
ofstream ofile("serial.bin");
cout << "size = " << serialize(ofile, a) << endl;
ofile.close();
return 0;
}
in.cpp:
#include <fstream>
#include "common.h"
int main() {
char buffer[1024];
ifstream ifile("serial.bin");
cout << "size = " << deserialize(ifile, buffer) << endl;
ifile.close();
A& a = *reinterpret_cast<A*>(buffer);
a.print();
return 0;
}
如果我的类没有虚函数,这似乎可以正常工作,但是
in.cpp 当他们这样做时会崩溃。
我的理解是out.cpp创建的vptr不适合in.cpp使用。
有什么可以做的,可能避免手动创建和维护一个 vtable?
【问题讨论】:
-
我宁愿建议寻找合适的序列化库(例如 boost 存档),为您做到这一点。您基本上有未定义的行为,原始转换仅适用于 POD 类型。
-
@user0042 代码应该转到微控制器,所以没有机会引入 Boost :( 加上我想了解。
-
在这种情况下,我建议使用 Google Protobuf 和 Nano-PB C 接口。您必须自己提供带有类的映射代码。不,没有办法以某种方式手动管理 vtable。
-
问题不仅在于 vtable 指针,还在于一般的指针。如果您将指针(或引用)保存到磁盘并将其加载到另一个程序中-它们现在有效的几率是多少?尽可能接近于零!
-
您无法通过重新解释某些字节来创建对象。 (如果可以,我们可以通过调用 memcpy 来替换复制构造函数)。使用构造函数创建对象。
标签: c++ serialization polymorphism