Я должен сериализовать карту в файл. Сначала я помещаю карту в байтовый буфер, затем записываю байтовый буфер в файл. В методе загрузки сначала прочитайте в байтовый буфер весь файл, затем заполните карту из байтового буфера. В настоящее время у меня есть этот код (без обработки файлов):
Сохранить метод:
map<int, BaseClass*> myMap;
map<int, BaseClass*>::iterator it;
ByteBuffer bb;
bb.putUInt(myMap.size());
for (it = myMap.begin(); it!= myMap.end(); it++){
bb.putUInt(it->first);
it->second->save(bb); // the save method put the static type first, then the data
}
Метод загрузки
...// get the map size from bb
for (int i=0; i<size; i++){
int key = bb.getUInt() // in the real code there isn't signed/unsigned mismatch
BaseClass* value = MyFactory.create(bb) // detailed later
myMap.insert(key,value);
}
MyFactory.create:
BaseClass* MyFactory::create( ByteBuffer& bb){
TypeEnum type = static_cast<TypeEnum>(bb.getUInt());
BaseClass* value;
switch (type){
case DerivedClass1:
value = new DerivedClass1()
break;
case DerivedClass2:
value = new DerivedClass2()
break;
// etc...
}
value->load(bb);
return value;
}
С этим решением у меня есть большой enum TypeEnum, длинный переключатель, и с каждым новым производным классом из базового класса я должен увеличивать их. Есть ли лучший способ сделать это?
Я думаю, что ваш подход правильный. Однако вы хотите рассмотреть следующие улучшения:
Используйте умный указатель внутри factory :: create. Потому что теперь это не исключение:
std::auto_ptr<BaseClass> MyFactory::create(ByteBuffer& bb)
{
TypeEnum type = static_cast<TypeEnum>(bb.getUInt());
std::auto_ptr < BaseClass > value;
switch (type)
{
case DerivedClass1:
value.reset(new DerivedClass1());
break;
case DerivedClass2:
value.reset(new DerivedClass2());
break;
}
value->load(bb);
return value;
}
Таким образом, в случае сбоя при загрузке у вас не будет утечки памяти.
На вашем месте я бы подумал об использовании Boost.Serialization библиотека.