To jest stara wersja strony!
Autor : Marcin Kocoń, G1ISI — Marcin Kocoń 2008/04/14 11:36
Poprzez serializację rozumiemy zapis instancji dowolnej klasy do pliku w sposób umożliwiający jej późniejszą rekonstrukcję.
Biblioteka boost:serialization umożliwia automatyczną (tzn. bez jakieś większej naszej ingerencji) serializację wybranych atrybutów. Dzięki wbudowanych funkcjom tej biblioteki jesteśmy w stanie w prosty (jednakże czasem mniej lub bardziej zróżnicowany) sposób dokonać serializacji następujących elementów :
Więcej informacji o dokładnym działaniu biblioteki na stronie Boost:serialization
// Praca domowa ZPR 2008L // Marcin Kocoń // temat : biblioteka boost:serialization #include <fstream> #include <iostream> // bedziemy zapisywac proste archwium w postaci tekstowej #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> // potrzebne do obslugi serializacji klas pochodnych #include <boost/serialization/base_object.hpp> #include <boost/serialization/deque.hpp> // nagłówek zawierający metodę(makro) do rozdzielenia funkcji serializacji #include <boost/serialization/split_free.hpp> #include <exception> // Klasa opisująca studenta class student { private: std::string imie; std::string nazwisko; public: student() {} student(const std::string& _imie, const std::string& _nazwisko){ imie = _imie; nazwisko = _nazwisko; } // Zestaw Set'ów i Get'ów między innymi do obsługi serializacji dla atrybutów prywatnych std::string& getImie() { return imie; } std::string& getNazwisko() { return nazwisko; } void setImie(const std::string& _imie) { imie = _imie; } void setNazwisko(const std::string& _nazwisko) {nazwisko = _nazwisko; } }; // Metoda serializacji nie będąca elementem klasy. Umożliwia zapisz/odczyt atrybutów // prywatnych. Jednakże, aby tego dokonać potrzeba jest rozczepienie domyślnej // metody serialize na dwie : save i load, a następnie połączenie ich w całość namespace boost { namespace serialization { template<class Archive> void save(Archive & ar, const student& g, const unsigned int version) { student g2 = const_cast<student&>(g); // usunięcie const, aby można było wywołać metodę getXXX ar << g2.getImie(); ar << g2.getNazwisko(); } template<class Archive> void load(Archive & ar, student& g, const unsigned int version) { std::string s1, s2; ar >> s1; ar >> s2; g.setImie(s1); g.setNazwisko(s2); } template<class Archive> inline void serialize(Archive & ar, student& g, const unsigned int version){ // złączenie load/save -> serialize split_free(ar, g, version); } } // namespace serialization } // namespace boost // Klasa opisująca budynek - klasa bazowa class budynek { private: // dzięki temu metoda serializacji ma dostęp do atrybutów prywatnych friend class boost::serialization::access; template <class Archive> // te dwie linijki są wzorcem, z którego void serialize(Archive& ar, const unsigned int version) // korzystamy zawsze przy serializacji { ar & identyfikator; // poszczególne atrybuty są dodawane do archiwum ar & nazwa; // poprzez użycie operatora '&' na archiwum ar & miasto; } std::string miasto; std::string nazwa; int identyfikator; protected: budynek(const int _id, const std::string& _nazwa, const std::string& _miasto) : identyfikator(_id), nazwa(_nazwa), miasto(_miasto) {} public: std::string& getMiasto() { return miasto; } std::string& getNazwa() { return nazwa; } int getId() { return identyfikator; } budynek() {} virtual ~budynek() {} }; // Klasa pochodna akademik, dziedzicząca po budynku class akademik : public budynek { private: // Standardowo dostęp do metod prywatnych dla serializacji friend class boost::serialization::access; template<class Archive> // metoda serializacji void serialize(Archive & ar, const unsigned int version) { // Zserializuj atrybuty z klasy bazowej ar & boost::serialization::base_object<budynek>(*this); // Kolekcje STL-owskie są automatycznie serializowane. // W podobny sposób działa także serializacja wskaźników // (= obiektów, na które wskazują) ar & studenci; } std::deque<student *> studenci; // Standardowa kolejka STL-owska public: akademik() {} akademik(const int _id, const std::string& _nazwa, const std::string& _miasto) : budynek(_id, _nazwa, _miasto) {} // Umożliwia dodanie studenta do kolekcji studentów void dodajStudenta(student* const _stud) { studenci.push_back(_stud); } // Zwraca ilość studentów w akademiku const int getIlStud() { return studenci.size(); } // Podaje dane studenta student* const podajDaneStudentaNr(const int _nr) { return studenci[_nr]; } virtual ~akademik() {} }; void zapisz_akademik(const akademik &s, const char* filename) { try{ // stworz archiwum std::ofstream ofs(filename); // zapisz w postaci archiwum tekstowego boost::archive::text_oarchive oa(ofs); oa << s; } catch(std::exception e) { std::cout << e.what() << std::endl; exit(1); } } void wczytaj_akademik(akademik &s, const char* filename) { try{ // otwórz archiwum std::ifstream ifs(filename); boost::archive::text_iarchive ia(ifs); // przywroc dane z uprzednio zapisanego archiwum ia >> s; } catch(std::exception e) { std::cout << e.what() << std::endl; exit(1); } } int main() { const char* filename = "ala_i_kot.dat"; // Nowy akademik + dwoch studentow akademik* ak1 = new akademik(1, "Riviera", "Warszawa"); ak1->dodajStudenta(new student("Jacek", "Jankowski")); ak1->dodajStudenta(new student("Adam", "Jakubowski")); //----- Zapis do archiwum ----- { zapisz_akademik(*ak1, filename); } // archiwum i output stream zamykane podczas wywolywania destruktora delete ak1; // Jakis czas pozniej.... akademik nowy; // ----- Odczyt z archiwum ----- { wczytaj_akademik(nowy, filename); } std::cout << "Nowy akademik : " << nowy.getId() << ", " << nowy.getNazwa() << ", " << nowy.getMiasto() << ", " << nowy.getIlStud() << "\n"; std::cout << "Mieszkancy : \n"; for (int i=0; i< nowy.getIlStud(); ++i) { std::cout << "[" << i << "] Imie : " << nowy.podajDaneStudentaNr(i)->getImie(); std::cout << " Nazwisko : " << nowy.podajDaneStudentaNr(i)->getNazwisko() << "\n"; } std::cout << "\n\n"; return 0; }