将继承的类存储到文件的更好方法
Better way to store inherited class to the file
这段代码有效,但正确的方法是什么?
我的意思是,我怎样才能消除read_in函数中的switch语句,或者处理动物类或其子类中的所有读取,这样我的read_in函数就可以像我的write_out函数一样简单?
我有一个装满猫和普通动物的vector<animal*> *animals
,我需要在文件中写入/读取/读取。
我省略了一些代码,所以帖子不会太大......
enum class animal_type
{
GENERIC_ANIMAL,
CAT
};
假设我有一只类动物
class animal
{
animal_type m_type;
string m_name;
virtual void write_binary(ofstream &out)
{
out.write((char*)(&m_type), sizeof(m_type)); //first 'animal_type'
out.write((char*)(&m_type), sizeof(m_type)); //second 'animal_type'
out.write(m_name.c_str(), m_name.size()+1);
{
virtual void read_binary(std::ifstream &in)
{
in.read((char*)(&m_type), sizeof(m_type)); //read the second animal type here
m_name = read_null_string(in);//this function returns next string from input
}
};
以及源自动物的类
class cat : public animal
{
bool m_is_cute;
void write_binary(std::ofstream &out)
{
animal::write_binary(out);
out.write((char*)(&m_is_cute), sizeof(m_is_cute));
}
void read_binary(std::ifstream &in)
{
animal::read_binary(in);
in.read((char*)(&m_is_cute), sizeof(m_is_cute));
}
};
我将它们写入这样的文件
void write_out(std::ofstream &out, std::vector<animal*> *animals)
{
int size = animals->size();
out.write((char*)(&size), sizeof(size));
for(animal* a : *animals)
{
a->write_binary(out);
}
}
并像这样从文件中读取它们
void read_in(std::ifstream &in, std::vector<animal*> *animals)
{
animals->clear();
int size;
in.read((char*)(&size), sizeof(size));
for(int i = 0; i< size; ++i)
{
animal_type type;
//read the first 'animal_type' here
in.read((char*)(&type), sizeof(type));
animal *a;
switch(type)
{
case(animal_type::GENERIC_ANIMAL):
a = new animal(in);//this constructor just calls the read_binary method
break;
case(animal_type::CAT):
a = new cat(in);//this constructor just calls the read_binary method
break;
}
animals->push_back(a);
}
}
这是(许多)选项中的一个:
首先,我们将enum class animal_type
更改为一个普通的旧枚举becaysuse,我们希望将其用作整数。如果不允许这样做,请将其保留为enum class animal_type
,并在以后使用static_cast<size_t>
进行转换。
enum animal_type
{
GENERIC_ANIMAL = 0, // must be 0. First index in array
CAT,
LAST, // must be last. Put no animals after it
FIRST = GENERIC_ANIMAL // makes it easy to loop FIRST to LAST
};
然后定义你所有的动物。
接下来,构建一个调用相应动物构造函数的函数数组。此数组必须与上面的枚举完全匹配。如果这是一个问题,请考虑改用std::map
。
std::function<animal *(std::ifstream &)> animalFactory[] =
{
[](std::ifstream & in) {return new animal(in);},
[](std::ifstream & in) {return new cat(in);}
};
关于 std::function 的文档
有关 Lambda 表达式的文档
接下来定义在发生坏事时要引发的异常。可以像
class Bogus_File_Exception: public std::exception
{
const char* what() const
{
return "File read failed.";
}
};
最后read_in
变成了
void read_in(std::ifstream &in, std::vector<animal*> & animals) // note the reference
{
animals.clear();
int size;
if (in.read((char*)(&size), sizeof(size))) // testing for successful read
{
for(int i = 0; i< size; ++i)
{
animal_type type;
if (in.read((char*)(&type), sizeof(type))) // testing again
{
if (type < animal_type::LAST)
{
animals.push_back(animalFactory[type](in));
}
else
{
throw Unknown_Animal_Exception();
}
}
else
{
throw Bogus_File_Exception();
}
}
}
else
{
throw Bogus_File_Exception();
}
}
相关文章:
- C++:将控制台输出存储在宏中更好吗
- FFmpeg:制作一个应用程序比直接使用ffmepg更好吗
- 初始化具有非默认构造函数的std::数组项的更好方法
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 为什么新的随机库比std::rand()更好
- 寻找一种更好的方法来表示无符号字符数组
- 有没有更好的方法来使用比特流解码文件格式?
- 在这种情况下,将数据存储在诸如SQLite之类的数据库中,还是存储在平面文本文件中更好
- 将继承的类存储到文件的更好方法
- 如何将输入与文件中的内容相匹配?我需要一个更好的解释
- 比 stat() 在 DIR 中查找文件的更好方法
- 使用SSD时,使用一个线程写入20个不同的文件比使用20个线程更好吗
- 有没有更好的方法来搜索文件中的字符串
- 在 c++ 中读取文件的更好方法是什么
- 是实时将数据写入文件更好,还是在程序关闭时写入文件更好
- 更好地理解makefile——在这种情况下如何生成.o文件
- 在测试项目中包含.cpp文件的更好方法
- 巨大的.cpp文件比从文本文件读取更好
- 还有什么比使用istream eof更好的方法来读取文件直到它结束呢?
- 是在单个头文件中定义全局(外部)变量更好,还是在它们各自的头文件中更好?