2012-03-06 27 views
6

Làm thế nào bạn sẽ tuần tự hóa/deserialize lớp này bằng cách sử dụng boost :: serialization?Tăng tuần tự hóa với con trỏ và hàm tạo mặc định

#include <vector> 

struct Foo { 
    struct Bar { 
     std::vector<int> * data; // Must point to Foo::data 

     Bar(std::vector<int> * d) : data(d) { } 
    }; 

    std::vector<int> data; 
    std::vector<Bar> elements; 

    Foo() { 
     // do very time consuming calculation to populate "data" and "elements" 
    } 
}; 

Hàm khởi tạo trong Foo không được thực thi khi đối tượng được tải từ dữ liệu tuần tự, nhưng nếu đối tượng được xây dựng mặc định thì hàm tạo phải được đánh giá.

Bạn có thể thêm một hàm tạo mặc định vào Bar, nhưng sau khi tuần tự hóa dữ liệu Foo :: Bar :: phải trỏ đến dữ liệu Foo ::.

EDIT: Sau đây là một việc thực hiện không làm việc cố gắng của tôi

Đây là nỗ lực của tôi dựa trên các gợi ý từ @Matthieu. Vấn đề là khi tôi deserialize Foo, tôi nhận được không có yếu tố trong Foo :: dữ liệu và Foo :: yếu tố.

struct Foo { 
    struct Bar { 
     std::vector<int> * data; 

     Bar() : data(0) { } 
     Bar(std::vector<int> * d) : data(d) { } 

     template<class Archive> 
     void serialize(Archive & ar, const unsigned int version) { 
      ar & data; 
     } 
    }; 

    std::vector<int> data; 
    std::vector<Bar> elements; 

    Foo() { 
     std::cerr << "Running default constructor" << std::endl; 
     data.push_back(1); 
     data.push_back(2); 
     data.push_back(3); 
     data.push_back(4); 
     data.push_back(5); 
     elements.push_back(Bar(&data)); 
     elements.push_back(Bar(&data)); 
     elements.push_back(Bar(&data)); 
    } 

    template<class Archive> 
    Foo(Archive & ar) { 
     ar >> data; // is this corrent? 
     ar >> elements; 
    } 

private: 
    BOOST_SERIALIZATION_SPLIT_MEMBER(); 
    friend class boost::serialization::access; 

    template<class Archive> 
    void save(Archive & ar, const unsigned int version) const { 
     const std::vector<int> * data_ptr = &data; 

     // should data be seriliazed as pointer... 
     // it is used as a pointer in Bar 
     ar << data_ptr; 
     ar << elements; 
    } 
}; 

int main(int argc, const char *argv[]) 
{ 
#if 0 
    // serialize 
    Foo foo; 
    boost::archive::text_oarchive oar(std::cout); 
    oar << foo; 

#else 
    // deserialize 
    boost::archive::text_iarchive oar(std::cin); 
    Foo foo(oar); 

#endif 
    std::cerr << foo.data.size() << std::endl; 
    std::cerr << foo.elements.size() << std::endl; 

    std::cerr << (&foo.data) << std::endl; 
    for(const auto& a : foo.data) 
     std::cerr << a << " "; 
    std::cerr << std::endl; 

    for(const auto& a : foo.elements) 
     std::cerr << a.data << " "; 
    std::cerr << std::endl; 

    return 0; 
} 

Trả lời

2

Có một phần trong tài liệu mô tả cách (de) tuần tự hóa các lớp với nhà thầu không mặc định. Xem here. Về cơ bản, bạn phải thực hiện hai chức năng được gọi là save_construct_dataload_construct_data trong không gian tên boost::serialization để ghi ra và đọc dữ liệu được sử dụng để tạo các phiên bản của lớp học của bạn. Sau đó, bạn có thể gọi một hàm tạo không mặc định là Foo từ hàm load_construct_data với các tham số cần thiết để tạo lại đối tượng Foo.


Dưới đây là một ví dụ làm việc dựa trên mã cập nhật của bạn:

Lưu ý rằng tôi đã sử dụng shared_ptr 's để làm rõ rằng data thành viên đăng bởi Foo và Bar đang tham chiếu điều tương tự.

#include <vector> 
#include <boost/archive/text_oarchive.hpp> 
#include <boost/archive/text_iarchive.hpp> 
#include <boost/serialization/vector.hpp> 
#include <boost/serialization/shared_ptr.hpp> 
#include <boost/serialization/scoped_ptr.hpp> 
#include <boost/shared_ptr.hpp> 
#include <iostream> 
#include <sstream> 

struct Foo { 
    struct Bar { 
     boost::shared_ptr< std::vector<int> > data; // Must point to Foo::data 

     Bar(boost::shared_ptr< std::vector<int> > d) : data(d) { } 

     template<class Archive> 
     void serialize(Archive & ar, const unsigned int version) 
     { 
      // ** note that this is empty ** 
     } 
    }; 

    boost::shared_ptr< std::vector<int> > data; 
    std::vector<Bar> elements; 

    Foo() : data(new std::vector<int>()) { 
     std::cerr << "Running default constructor" << std::endl; 
     data->push_back(1); 
     data->push_back(2); 
     data->push_back(3); 
     data->push_back(4); 
     data->push_back(5); 
     elements.push_back(Bar(data)); 
     elements.push_back(Bar(data)); 
     elements.push_back(Bar(data)); 
    } 

    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) 
    { 
     // ** note that this is empty ** 
    } 

    Foo(
     boost::shared_ptr< std::vector<int> > const & data_, 
     std::vector<Bar> const & elements_) : data(data_), elements(elements_) 
    { 
     std::cout << "cheap construction" << std::endl; 
    } 
}; 

namespace boost { namespace serialization { 

template<class Archive> 
inline void save_construct_data(
    Archive & ar, const Foo * foo, const unsigned int file_version 
){ 
    ar << foo->data << foo->elements; 
} 

template<class Archive> 
inline void load_construct_data(
    Archive & ar, Foo * foo, const unsigned int file_version 
){ 
    boost::shared_ptr< std::vector<int> > data; 
    std::vector<Foo::Bar> elements; 

    ar >> data >> elements; 

    ::new(foo)Foo(data, elements); 
} 

template<class Archive> 
inline void save_construct_data(
    Archive & ar, const Foo::Bar * bar, const unsigned int file_version 
){ 
    ar << bar->data; 
} 

template<class Archive> 
inline void load_construct_data(
    Archive & ar, Foo::Bar * bar, const unsigned int file_version 
){ 
    boost::shared_ptr< std::vector<int> > data; 

    ar >> data; 

    ::new(bar)Foo::Bar(data); 
} 

}} 

int main() 
{ 
    std::stringstream ss; 

    { 
    boost::scoped_ptr<Foo> foo(new Foo()); 

    std::cout << "size before serialization is: " << foo->data->size() << std::endl; 

    boost::archive::text_oarchive oa(ss); 
    oa << foo; 
    } 

    { 
    boost::scoped_ptr<Foo> foo; 

    boost::archive::text_iarchive is(ss); 
    is >> foo; 

    std::cout << "size after deserialization is: " << foo->data->size() << std::endl; 
    } 

    return 0; 
} 
+0

Có, tôi đã thấy điều này. Nhưng làm thế nào bạn sẽ viết quá tải tải? Hàm khởi tạo mặc định của Foo không được gọi. – Allan

+0

@Allan: bạn sẽ cần phải thêm một hàm tạo cụ thể cho việc deserialization. Ví dụ: một hàm tạo cần lưu trữ tăng trong đối số. –

+0

@Matthieu Ahh .. đơn giản như thế này, cảm ơn. Điều gì về Foo :: dữ liệu, tôi nên serialize nó như là một con trỏ, và sau đó làm một trao đổi khi deserializing? – Allan

Các vấn đề liên quan