希望得到一些帮助,因为我觉得我的头撞在门上已经很久了,但无济于事。
目标:使用逐位移位运算符从Dog对象中提取一个int,并将其序列化为属于SerializedObject的char指针,使用std::ios:binary将该char指针保存到std::ofstream的.dat文件,然后使用std:::ios::binary将.dat文件读取到std::ifstream,最后通过反序列化SerializedObject来创建Dog对象。
问题:
- Dog::Serialize的逐位移位似乎执行不正确。字符指针的前3个索引始终为0,最后一个索引为整数。小数应该转换为二进制1110或0000000000001110,但结果却是(0((0(
- 保存到.dat文件似乎无法正常工作。即使tSo->mBuffer是上面的,它应该将文本保存为单个,而不是保存为PçN
- 当加载.dat文件时,它为dog2->mAge。这可能与它保存的文本的二进制值01010000 1100011 10100111 01001110 0000000 1 00001010有关,而不是只有1110。这与Dog::CreateFromSO的循环似乎只是在乘以mAge值相结合,似乎是造成这种情况的根本原因
我和同事们一起查看了这个程序,我们有几乎相同的代码。我在Dog::Serialize或Dog::CreateFromSO方面所做的一切似乎都不会对这个结果产生影响。我真的不知所措。
Dog.h
#pragma once
#include <list>
#include "SerializedObject.h"
class Dog
{
public:
static const int SID = 1;
static Dog* NewDog();
static void DeleteAll() {}
static Dog* CreateFromSO(SerializedObject* tSO);
static Dog* FindDogFromID( int tID ) { return nullptr; }
int mAge = 0;
SerializedObject* Serialize();
private:
int mObjectID = 0;
Dog();
static std::list<Dog*> sAllDogs;
};
Dog.cpp
#include "Dog.h"
Dog* Dog::NewDog()
{
Dog* result = new Dog;
return result;
}
Dog::Dog() {
mAge = 14;
mObjectID = 1;
}
SerializedObject* Dog::Serialize()
{
SerializedObject* result = new SerializedObject;
result->mFullSize = sizeof(int);
result->mClassID = this->SID;
result->mBufferSize = sizeof(int);
result->mBuffer = new char[result->mBufferSize];
result->mBuffer[0] = (mAge >> 24) &0xFF;
result->mBuffer[1] = (mAge >> 16) &0xFF;
result->mBuffer[2] = (mAge >> 8) &0xFF;
result->mBuffer[3] = mAge & 0xFF;
return result;
}
Dog* Dog::CreateFromSO(SerializedObject* tSO)
{
Dog* result = new Dog;
result->mAge = 0;
for (int i = 0; i < 4; i++)
{
result->mAge <<= 8;
result->mAge |= tSO->mBuffer[i];
}
return result;
}
SerializedObject.h
#pragma once
struct SerializedObject
{
int mFullSize = -1;
int mClassID = -1;
int mBufferSize = -1;
char* mBuffer= nullptr;
};
main.cpp
#include "SerializedObject.h"
int main()
{
std::ofstream os;
os.open("APLO123.dat", std::ios::binary);
Dog* dog1 = Dog::NewDog();
SerializedObject* tSo = dog1->Serialize();
for (int i = 0; i < 4; i++)
{
os.put(tSo->mBuffer[i]);
}
os.close();
SerializedObject* tSo2 = new SerializedObject;
char* buffer = new char[sizeof(int)];
std::ifstream is;
is.open("APLO123.dat", std::ios::binary);
is.read(buffer, sizeof(int));
tSo2->mBuffer = buffer;
Dog* dog2 = Dog::CreateFromSO(tSo2);
}
Dog::Serialize返回之前的mBuffer调试显示值0 0 14
DatFile显示PçN输出到.dat
ifstream.read之后的主缓冲区读取错误4 0 0 0
结果的值->Dog::CreateFromSO返回前的mAge显示价值是如何巨大的:67108864
编辑:添加了Dog.h、Dog.cpp的其余部分和SerializedObject.h
您可以进行序列化和反序列化。
但是,还有许多设计缺陷需要修复。
出于没人能理解的原因,你到处都在使用新的。尽管从来没有必要。而且你永远不会删除你分配的内存。你这样做的方式真的很难解决。
然后,您不明白成员函数应该在自己的数据成员上工作,而不是在其他类的成员上工作。
在您的";狗;类,您有一个创建不同dog的函数。它不设置"0"的值;这个";狗,但创造了一个新的。这是错误的。甚至编译器也会为Dog* dog2 = Dog::CreateFromSO(tSo2);
行发出一个错误提示。这完全是错误的设计。
如果我查看您的代码,那么我看不到mAge被初始化为某个值。你似乎在文件中存储了不确定的值,然后想知道你读回了什么。
为了向您展示基本的序列化/反序列化是有效的,请参阅以下代码:
#include <iostream>
#include <fstream>
struct SerializedObject {
size_t mFullSize{};
unsigned int mClassID;
size_t mBufferSize{};
char* mBuffer{};
};
struct Dog {
unsigned int SID{};
unsigned int mAge{};
SerializedObject* Serialize();
Dog* CreateFromSO(SerializedObject* tSO);
};
SerializedObject* Dog::Serialize() {
SerializedObject* result = new SerializedObject;
result->mFullSize = sizeof(int);
result->mClassID = this->SID;
result->mBufferSize = sizeof(int);
result->mBuffer = new char[result->mBufferSize];
result->mBuffer[0] = (mAge >> 24) & 0xFF;
result->mBuffer[1] = (mAge >> 16) & 0xFF;
result->mBuffer[2] = (mAge >> 8) & 0xFF;
result->mBuffer[3] = mAge & 0xFF;
return result;
}
Dog* Dog::CreateFromSO(SerializedObject* tSO) {
Dog* result = new Dog;
result->mAge = 0;
for (int i = 0; i < 4; i++)
{
result->mAge <<= 8;
result->mAge |= tSO->mBuffer[i];
}
return result;
}
int main() {
std::ofstream os;
os.open("APLO123.dat", std::ios::binary);
Dog* dog1 = new Dog();
dog1->SID = 1;
dog1->mAge = 42;
SerializedObject* tSo = dog1->Serialize();
for (int i = 0; i < 4; i++)
{
os.put(tSo->mBuffer[i]);
}
os.close();
SerializedObject* tSo2 = new SerializedObject;
char* buffer = new char[sizeof(int)];
std::ifstream is;
is.open("APLO123.dat", std::ios::binary);
is.read(buffer, sizeof(int));
tSo2->mBuffer = buffer;
Dog dogTemp;
Dog* dog2 = dogTemp.CreateFromSO(tSo2);
std::cout << dog2->mAge << 'n';
}
但这个代码是错误的,永远不应该使用它。尤其是内存泄漏是一个严重的错误。
遗憾的是,您没有提供足够的信息,因此我可以向您展示完整的重新编码。特别是因为我们的老师可能希望您了解一般的序列化,使用框架或稍后讨论工厂。
不管怎样。这里有一些最小的改进例子。仍然不是好的和错误的设计。
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
struct SerializedObject {
size_t mFullSize{};
unsigned int mClassID;
size_t mBufferSize{};
std::vector<char> mBuffer{};
};
struct Dog {
unsigned int SID{};
unsigned int mAge{};
SerializedObject Serialize();
void CreateFromSO(SerializedObject& tSO);
};
SerializedObject Dog::Serialize() {
SerializedObject result{};
result.mFullSize = sizeof(int);
result.mClassID = this->SID;
result.mBufferSize = sizeof(int);
result.mBuffer.resize(result.mFullSize);
result.mBuffer[0] = (mAge >> 24) & 0xFF;
result.mBuffer[1] = (mAge >> 16) & 0xFF;
result.mBuffer[2] = (mAge >> 8) & 0xFF;
result.mBuffer[3] = mAge & 0xFF;
return result;
}
void Dog::CreateFromSO(SerializedObject& tSO) {
mAge = 0;
for (int i = 0; i < 4; i++) {
mAge <<= 8;
mAge |= tSO.mBuffer[i];
}
}
std::string filename{ "APLO123.dat" };
int main() {
std::ofstream os(filename, std::ios::binary);
if (os) {
Dog dog1{ 1,42 };
SerializedObject tSo = dog1.Serialize();
for (int i = 0; i < 4; i++)
{
os.put(tSo.mBuffer[i]);
}
os.close();
std::ifstream is(filename, std::ios::binary);
if (is) {
SerializedObject tSo2;
tSo2.mBuffer.resize(sizeof(int));
is.read(tSo2.mBuffer.data(), sizeof(int));
Dog dog2;
dog2.CreateFromSO(tSo2);
std::cout << dog2.mAge << 'n';
}
else std::cerr << "nError: Could not open '" << filename << "' for reading.n";
}
else std::cerr << "nError: Could not open '" << filename << "' fow writing.n";
}