2009-08-26 7 views
11

Je voudrais sérialisation/cours unserialize suivantes:Comment sérialiser des classes de modèles dérivés avec Boost.serialize?

class Feature{ 
... 
virtual string str()=0; 
}; 

template<typename T> 
class GenericFeature : public Feature{ 
T value; 
... 
virtual string str(); 
}; 

J'ai lu boost.serialize docs et le sayed que vous devez inscrire les classes. Je peux les enregistrer dans le constructeur. Mais il y aura des problèmes avec le chargement, car l'enregistrement sera dynamique, et non statique (comme je l'ai compris, vous devez enregistrer les classes avant la sérialisation/désérialisation).

Comment sauvegarder/charger ce type de classes?

Répondre

15

d'abord dire stimuler cette fonctionnalité est abstraite, est pas toujours nécessaire:

BOOST_SERIALIZATION_ASSUME_ABSTRACT(Feature); 

La méthode de sérialisation devrait ressembler plus ou moins comme ceci:

template<class Archive> 
void Feature::serialize(Archive & ar, const unsigned int version) 
{ 
    ar & BOOST_SERIALIZATION_NVP(some_member); 
} 


template<typename T,class Archive> 
void GenericFeature<T>::serialize(Archive & ar, const unsigned int version) 
{ 
    ar & boost::serialization::base_object<Feature>(*this); //serialize base class 
    ar & BOOST_SERIALIZATION_NVP(some_other_member); 
} 

Maintenant, le point délicat est de classe s'inscrire en sérialiser/désérialiser:

boost::archive::text_iarchive inputArchive(somesstream); 

boost::archive::text_oarchive outputArchive(somesstream); 

//something to serialize 
Feature* one = new GenericFeature<SomeType1>(); 
Feature* two = new GenericFeature<SomeType2>(); 
Feature* three = new GenericFeature<SomeType3>(); 

//register our class, must be all of posible template specyfication  
outputArchive.template register_type< GenericFeature<SomeType1> >(); 
outputArchive.template register_type< GenericFeature<SomeType2> >(); 
outputArchive.template register_type< GenericFeature<SomeType3> >(); 

// now simply serialize ;-] 
outputArchive << one << two << three; 

// register class in deserialization 
// must be the same template specification as in serialize 
// and in the same correct order or i'm get it wrong ;-D 
inputArchive.template register_type< GenericFeature<SomeType1> >(); 
inputArchive.template register_type< GenericFeature<SomeType2> >(); 
inputArchive.template register_type< GenericFeature<SomeType3> >(); 

Feature* another_one; 
Feature* another_two; 
Feature* another_three; 

// and deserialize ;-] 
inputArchive >> another_one >> another_two >> another_three; 

Si vous avez besoin de masquer explicitement l'enregistrement somewh Avant de le rendre plus automatique, il y a l'idée de créer un modèle de foncteur spécial qui enregistre une classe dérivée, crée tout ce qui est disponible et place dans une seule liste, qu'une méthode statique de classe Feature les enregistre tous. Cependant, le problème sera que vous avez besoin d'enregistrement pour toutes les versions de l'archive, en ce moment je ne sais pas si l'archive polymorphique fera le travail ou pas.

+0

Je pense qu'il y a un bogue dans la ligne 11 de la première boîte de code. Si je ne me trompe pas, vous devriez avoir "ar &" à gauche de "boost :: serialization :: base_object". Bonne réponse cependant! –

+3

@lionbest: Vous ne devriez pas utiliser 'BOOST_SERIALIZATION_BASE_OBJECT_NVP' au lieu de' boost :: serialization :: base_object (* this); ' – Cookie

+0

Je pense que vous voudrez peut-être spécifier le nom si vous avez plus d'une classe de base. Je ne pense pas que cette macro soit nécessaire ici, mais bien sûr, vous voudrez peut-être en avoir une. – Arpegius

Questions connexes