im试图以我自己的方式创建一个函数来序列化一个类。我正在使用一个模板来保存每种形式的原始变量。即时通讯在我的序列化功能中出现错误。我不想我的元素在我的结构b / c中是静态的,我想保存许多不同的随机元素,请帮忙!
struct _PVS
{
public:
template<typename _PV> _PVS(_PV &PV)
: ele(PV)
{}
template<typename _PV> _PV ele;
};
class player_one {
std::vector<_PVS*> serializing;
const string PL_name = "JOHN!";
unsigned short int hp = 100;
unsigned short int shield = 55;
string fav_food = "soup.";
public:
player_one() {
serializing.push_back(new _PVS(PL_name));
serializing.push_back(new _PVS(hp));
serializing.push_back(new _PVS(shield));
serializing.push_back(new _PVS(fav_food));
}
void serialclass() {
ofstream _F;
string temp;
_F.open("player_one.log");
for (int i = 0; i < serializing.size(); i++) {
temp = (std::string)serializing[i].ele;
//getline to pass in whole lines for data for serializing
}
};
};
答案 0 :(得分:0)
下面是一个示例,说明了如何对低级文件格式进行序列化。请注意,我们只知道如何序列化两个字段类型(let x = 4;; (* Declare x *)
let f y = x + y;; (* Use x *)
let x = 5;; (* Declare a new variable with the same name as x *)
assert (f 10 = 14);; (* The x = 4 definition is used, as x is immutable *)
和uint16_t
)。您可以根据需要专门化其他类型。
我们要做的第一件事是选择一种数据格式。我在下面使用了一种基于块的简单方法,其中为每个字段的类型和长度保留了两个字节。每当您要序列化字段时,首先要写一个代表该类型的数字,然后写一个指示标头后面有多少字节的数字。
这被称为可变长度编码。
std::string
注意:下面的字符串以十六进制格式编码。字符串不以null结尾,以节省二进制格式的空间。反序列化时,您必须重新应用空字节终止符。
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <cstdint>
#include <iomanip>
using namespace std;
enum class SerializedType {
Unknown,
UnsignedShortInteger,
String
};
struct mapInt {
public:
const uint8_t first;
const uint8_t second;
mapInt(uint16_t value)
: first((value & 0xff00)>>8),
second(value & 0xff) {
}
};
std::vector<uint8_t> toWireFormat(const uint16_t& value) {
const auto mapped = mapInt(value);
const std::vector<uint8_t> data = {
static_cast<uint8_t>(SerializedType::UnsignedShortInteger),
2,
mapped.first,
mapped.second
};
return data;
}
std::vector<uint8_t> toWireFormat(const std::string& value) {
std::vector<uint8_t> data;
data.resize(value.size() + 2);
data[0] = static_cast<uint8_t>(SerializedType::String);
data[1] = static_cast<uint8_t>(value.size());
for (auto i = 0; i < value.size(); ++i) {
data[i+2] = value.at(i);
}
return data;
}
std::string serializedTypeAsString(SerializedType type) {
switch (type) {
case SerializedType::Unknown:
return " Unknown";
case SerializedType::UnsignedShortInteger:
return "uint16_t";
case SerializedType::String:
return " string";
}
}
template<class T>
void appendData(std::vector<uint8_t>& data, const T& value) {
const auto buffer = toWireFormat(value);
data.insert(data.end(), buffer.begin(), buffer.end());
}
class PlayerOne {
public:
const string name;
uint16_t hp;
uint16_t shield;
string favFood = "soup";
PlayerOne() = default;
~PlayerOne() = default;
void serialize(std::vector<uint8_t>& data) const {
appendData(data, name);
appendData(data, hp);
appendData(data, shield);
appendData(data, favFood);
};
};
int main()
{
PlayerOne ready = { "JOHN!", 100, 55, "Soup" };
PlayerOne two = { "Sarah", 250, 0, "Cake" };
vector<uint8_t> output;
ready.serialize(output);
two.serialize(output);
cout << "Serialized two objects into " << output.size() << " bytes." << endl;
size_t i = 0;
while (i < output.size()) {
const auto typeString = serializedTypeAsString(
static_cast<SerializedType>(output.at(i)));
const int length = output.at(i+1);
cout << "\nType: " << typeString << ", Length: " << length << ", Data: ";
i += 2;
if ((i+length) > output.size()) {
break;
}
for (size_t j = i; j < (i+length); ++j) {
cout << hex << setfill('0') << setw(2) << static_cast<int>(output.at(j));
}
i += length;
}
cout << endl;
return 0;
}