我几周前开始学习C ++,现在我的项目出现了问题。
我想编写模板,允许我将对象保存到二进制数据中,然后再加载它们。这是这些模板的代码:
#ifndef TOOLS_H
#define TOOLS_H
#include <fstream>
#include <string>
namespace Tools
{
template <class T>
void writeBinaryFile(std::string filename, T object)
{
std::ofstream of(filename, std::ios::out | std::ios::binary);
of.write((char*) &object, sizeof(T));
of.close();
}
template <class P>
P readBinaryFile(std::string filename)
{
P temp;
std::ifstream ifs(filename, std::ios::in | std::ios::binary);
ifs.read((char*) &temp, sizeof(P));
ifs.close();
return temp;
}
}
#endif
我创建了一个名为GameSettings的类。标题数据是:
#ifndef GAMESETTINGS_H
#define GAMESETTINGS_H
#include <iostream>
#include <string>
#include "SFML\Graphics.hpp"
class GameSettings
{
public:
GameSettings();
GameSettings(std::string playerName, bool sound, int volume, int level);
~GameSettings();
void setPlayerName(std::string playername){ playerName = playername; };
void setSound(bool sound){ this->sound = sound; };
void setVolume(int volume){ this->volume = volume; };
void setLevel(int level){ this->level = level; };
const std::string getPlayerName() { return playerName; }
const bool getSound() { return sound; }
const int getVolume() { return volume; }
const int getLevel() { return level; }
private:
std::string playerName;
bool sound;
int volume;
int level;
};
#endif
使用cpp-data:
#include "GameSettings.h"
GameSettings::GameSettings(std::string playerName, bool sound, int volume, int level)
{
this->playerName = playerName;
this->sound = sound;
this->volume = volume;
this->level = level;
}
GameSettings::GameSettings():
playerName(""),
sound(true),
volume(0),
level(0)
{
}
GameSettings::~GameSettings()
{
}
当我启动主函数时:
#include <iostream>
#include "GameSettings.h"
#include "Tools.h"
int main()
{
GameSettings* gs = new GameSettings("Andrew", true, 100, 3);
Tools::writeBinaryFile<GameSettings>("gamesettings.bin", *gs);
gs->setPlayerName("TEST");
*gs = Tools::readBinaryFile<GameSettings>("gamesettings.bin");
std::cout << gs->getPlayerName();
std::getchar();
return 0;
}
发生错误:
Mohrhuhn.exe中0x5a1cad54(msvcp100d.dll)的未处理异常:0xC0000005:访问冲突写入位置0xfeeefeee。
有人能帮助我吗?
真诚地,安德鲁
答案 0 :(得分:4)
我认为麻烦的根源是
*gs = Tools::readBinaryFile<GameSettings>("gamesettings.bin");
您将原始字节读取到包含std :: string的变量。它可能会破坏它内部的char指针。因此,对playerName的任何调用都应该失败或导致UB。
这种方式只能读/写POD类型。我在另一个网页上找到了更多:http://www.cplusplus.com/forum/general/39764/
答案 1 :(得分:3)
您为序列化对象而实现的模板将无效,因为将std::string
强制转换为char*
并保存sizeof(std::string)
将无法保存字符串的内容。
检查保存的文件,但我想你需要实现正确的序列化和反序列化。
答案 2 :(得分:2)
首先通过从内存中转储二进制文件来写下二进制文件是个坏主意,因为你可能会遇到很多其他问题(例如浅拷贝,polimorphism等等)。
return temp;
在函数退出后,您将返回一个正在销毁的临时对象。
将您的代码更改为
gs = Tools::readBinaryFile<GameSettings>("gamesettings.bin");
...
template <class P>
P* readBinaryFile(std::string filename)
{
P* temp = new P();
std::ifstream ifs(filename, std::ios::in | std::ios::binary);
ifs.read((char*) temp, sizeof(P));
ifs.close();
return temp;
}
一切都会正常运作(psst。记得释放记忆!)